2010-06-16 4 views
1

У меня есть куча логических опций для таких вещей, как «приемлемые типы платежей», которые могут включать в себя такие вещи, как наличные деньги, кредитная карта, чек, paypal и т. Д. Вместо того, чтобы иметь полдюжины булевых в моей БД, я могу просто использовать целое число и присвоить каждому способ оплаты за целое число, например, такНедостатки использования целого числа в виде битового поля?

PAYMENT_METHODS = (
    (1<<0, 'Cash'), 
    (1<<1, 'Credit Card'), 
    (1<<2, 'Cheque'), 
    (1<<3, 'Other'), 
) 

, а затем запросить конкретный бит в Python, чтобы получить флаг. Я знаю, это означает, что база данных не может индексировать по определенным флагам, но есть ли другие недостатки?

Почему я это делаю: у меня уже около 15 булевых элементов, разделенных на 3 разных логических «набора». Это уже много полей, и использование 3 таблиц «многие-ко-многим» для сохранения множества данных, которые редко меняются, кажется неэффективным. Использование целых чисел позволяет мне добавить до 32 флагов в каждое поле без необходимости вообще изменять БД.

ответ

1

Если вы можете ограничить свой вариант использования одним или несколькими наборами значений, которые могут иметь только один бит true за раз, возможно, вы могли бы использовать перечисления в своей базе данных. Вы получите лучшее из обоих миров, поддерживаемое как примечания btreat, и все еще меньше (и проще), чем несколько булевых.

Поскольку это невозможно, я согласен с вашим первоначальным утверждением и перейду с битовым полем. Однако я бы использовал/создавал битовую оболочку, так что в вашем коде вы не имеете дело с переворачиванием и смещением битов напрямую - это становится трудно поддерживать и отлаживать, как говорит btreat, но вместо этого обрабатывать его как список или словарь и конвертировать в/из битового поля, когда это необходимо.

Some commentary on enums/bitfields in Django

+0

(1) Как я могу использовать перечисление? В перечислении хранится * один * из нескольких вариантов (думаю, переключатели), а не несколько флагов (думаю, флажки). (2) Django tag == недостаточно контролирует, какой тип данных используется. – mpen

+0

Извиняюсь, я не понимал, что вам нужен этот дополнительный контроль. Ваш пример (тип оплаты) - это использование типа радиокнопки, и я вскочил на это. Если вам нужно несколько флагов true за раз, перечисления действительно не работают. Я переписал свой ответ. – dimo414

+0

Да ... Я думаю, это был плохой пример. В моем случае пользователи * могут * проверить более одного типа оплаты. Я не уверен, что бит-полем действительно необходимо. Мне очень легко работать с битами, если вы просто немного перепутаете. Однако было бы неплохо, если бы я мог давать имена для разных флагов, а не запоминать целые числа. – mpen

6

Главный недостаток, который я могу придумать, - это ремонтопригодность. Кто-то, кто пишет запрос к базе данных, должен понимать бит-соглашение, а не иметь возможность использовать более понятный для пользователя набор столбцов. Кроме того, если один из «принятых типов платежей» удален, сами данные должны быть перенесены, а не просто отбрасывать столбец в таблице.

+0

Почему данные должны быть перенесены? У вас просто есть неиспользуемый бит, к которому вы больше не будете обращаться. – mpen

+1

Мотивация для удаления неиспользуемого поля (будь то в виде столбца бит или столбца) - это упрощение приложения и, следовательно, улучшение ремонтопригодности. Однако вы совершенно правы. Приложение будет продолжать функционировать правильно, даже если бит не был удален. – btreat

2

Это не самое худшее, но может быть и лучший способ.

Определять таблица называется PaymentTypes

id, paymentId, key (string), value (boolean)

Теперь вы просто заполнить эту таблицу с тем, что вы хотите. Нет длинного столбца булевых элементов, и вы можете динамически добавлять новые типы. Недостатком этого является то, что значение по умолчанию для всех логических значений равно NULL или false.

+0

Вы имеете в виду добавить таблицу «многие ко многим» для типов платежей? Я думал об этом ... но это дополнительный слой, который на самом деле не кажется необходимым. – mpen

+0

@Mark, от одного до многих, но это немного хлопот. У вас также может быть много булевых столбцов в таблице с внешним ключом для платежей. –

+1

@Bryon: Почему это будет один для многих? Каждая партия может принимать несколько типов платежей, и каждый тип оплаты может принадлежать многим поставкам = m2m. Следовательно, битполе, а не просто перечисление. – mpen

1

Я думаю, что предыдущие плакаты оба были правильными. Самый чистый способ сделать это в «реляционной» базе данных - это определить новую таблицу отношений, в которой хранятся типы платежей. На практике, однако, это, как правило, больше хлопот, чем это стоит.

Использование перечислений в вашем коде и использование чего-либо подобного в БД (проверка ограничений в Oracle, AFAIK) должно помочь сохранить его поддерживаемым и очевидным для бедной души, кто будет работать над новым типом, много лет после того как вы оставите

2

Не знаете, какую базу данных вы используете, но MySQL имеет set type.

+1

Не знал, что этот тип существует. Классно! Я не думаю, что Django поддерживает его. – mpen

Смежные вопросы