Булево поле в Oracle

145

Вчера я хотел добавить логическое поле в таблицу Oracle. Однако в Oracle нет логического типа данных. Кто-нибудь здесь знает лучший способ симулировать логическое значение? Погуглив тему обнаружил несколько подходов

  1. Используйте целое число и просто не удосуживайтесь присвоить ему что-либо кроме 0 или 1.

  2. Используйте поле char с «Y» или «N» в качестве единственных двух значений.

  3. Используйте перечисление с ограничением CHECK.

Знают ли опытные разработчики Oracle, какой подход является предпочтительным / каноническим?

Эли Кортрайт
источник
195
Мне бы хотелось, чтобы у Oracle был wallтип данных, чтобы я мог разбить себе голову при использовании логических значений.
Грег

Ответы:

82

Я нашел эту ссылку полезной.

Вот параграф, освещающий некоторые плюсы и минусы каждого подхода.

Наиболее часто встречающийся дизайн - это имитация множества логических флагов, которые используют представления словаря данных Oracle, выбирая «Y» для true и «N» для false. Однако для правильного взаимодействия с хост-средами, такими как JDBC, OCCI и другими средами программирования, лучше выбрать 0 для false и 1 для true, чтобы он мог корректно работать с функциями getBoolean и setBoolean.

В основном они защищают метод № 2, для эффективности, используя

  • значения 0/1 (из-за совместимости с JDBC и getBoolean()т. д.) с проверочным ограничением
  • тип полукокса (потому что оно использует меньше места , чем число).

Их пример:

create table tbool (bool char check (bool in (0,1));
insert into tbool values(0);
insert into tbool values(1);`
ColinYounger
источник
31
Я не советую использовать 'N' и 'Y', поскольку это зависит от языка. Англоязычные люди иногда забывают, что большая часть мира не представляет концепцию истины буквой Y. Напротив, значение 0 и 1 постоянно в языковых барьерах.
Эндрю Спенсер
7
0 и 1 как логические значения не согласуются в компьютерных науках - языки сценариев оболочки имеют тенденцию иметь 0 как успех, и ненулевые как сбой, в то время как языки типа C имеют тенденцию иметь 0 как сбой, так и ненулевые как успех.
Фил
41
Как булевы значения, они однозначны. Коды возврата процесса не являются логическими значениями.
Эндрю Спенсер
13
Почему весь этот абзац из предоставленной ссылки был проигнорирован в этом ответе? «Наиболее часто встречающийся дизайн - это имитация множества логических флагов, используемых представлениями словаря данных Oracle, с выбором« Y »для true и« N »для false. Однако для корректного взаимодействия с хост-средами, такими как JDBC, OCCI, и в других средах программирования лучше выбрать 0 для false и 1 для true, чтобы он мог корректно работать с функциями getBoolean и setBoolean. " Они утверждают, что хотя «Y / N» является обычным явлением, рекомендуется использовать «0/1» для повышения совместимости с хост-средами.
justin.hughey
28

Сам Oracle использует Y / N для логических значений. Для полноты следует отметить, что pl / sql имеет логический тип, а не только таблицы.

Если вы используете поле, чтобы указать, нужно ли обрабатывать запись или нет, вы можете рассмотреть возможность использования Y и NULL в качестве значений. Это делает очень маленький (быстро читаемый) индекс, который занимает очень мало места.

Ли Риффель
источник
7
+1 Хороший вопрос о внутренних представлениях и таблицах Oracle, использующих Y / N. Если Oracle делает это таким образом, это должно быть правильно! :)
Джеффри Кемп
Можете ли вы объяснить, как Y и NULL составляют небольшой индекс по сравнению с Y и N?
Styfle
6
NULL не индексируются в Oracle, поэтому, если ваш индекс содержит несколько символов Y, но в основном NULL, у вас будет очень маленький индекс.
Ли Риффель
25

Чтобы использовать наименьшее количество места, вы должны использовать поле CHAR, ограниченное 'Y' или 'N'. Oracle не поддерживает типы данных BOOLEAN, BIT или TINYINT, поэтому один байт CHAR настолько мал, насколько вы можете получить.

Билл Ящерица
источник
19

Наилучший вариант - 0 и 1 (в виде чисел - другой ответ предлагает 0 и 1 в качестве CHAR для эффективности использования пространства, но для меня это слишком сложно), используя NOT NULL и проверочное ограничение для ограничения содержимого этими значениями. (Если вам нужно, чтобы столбец обнулялся, то вы имеете дело не с логическим значением, а с перечислением трех значений ...)

Преимущества 0/1:

  • Независимый от языка. «Y» и «N» было бы хорошо, если бы все использовали это. Но они этого не делают. Во Франции они используют «O» и «N» (я видел это своими глазами). Я не программировал в Финляндии, чтобы видеть, используют ли они там «E» и «K» - без сомнения, они умнее этого, но вы не можете быть уверены.
  • Соответствует практике в широко используемых языках программирования (C, C ++, Perl, Javascript)
  • Играет лучше с прикладным уровнем, например, Hibernate
  • Приводит к более сжатому SQL, например, чтобы узнать, сколько бананов готово к употреблению select sum(is_ripe) from bananasвместо select count(*) from bananas where is_ripe = 'Y'или даже (юк)select sum(case is_ripe when 'Y' then 1 else 0) from bananas

Преимущества «Y» / «N»:

  • Занимает меньше места, чем 0/1
  • Это то, что предлагает Oracle, поэтому может быть, что некоторые люди более привыкли к

Другой автор предложил «Y» / ноль для повышения производительности. Если вы доказали, что вам нужна производительность, то достаточно справедливо, но в противном случае избегайте, так как это делает запросы менее естественными ( some_column is nullвместо some_column = 0), и в левом соединении вы будете путать ложность с несуществующими записями.

Эндрю Спенсер
источник
3
Вы обнаружите, что в наши дни многие логические значения являются TriState, то есть true, false и unknown. который идеально подходит для нулевой идеи базы данных. просто потому, что много раз, зная, что ответ не был дан, жизненно важно
MikeT
1
Да, истина-ложь-неизвестность может потребоваться, хотя, если бы я был разборчив (а я), я бы сказал, что это не должно быть описано как логическое значение, потому что это не так.
Эндрю Спенсер
2
если вы хотите быть разборчивым, вы можете использовать один и тот же аргумент для каждого типа данных. как в строгом определении целое число, double (я думаю, я должен сказать, что двойная длина дополняет число с плавающей запятой), двоичное, строковое и т. д. все предполагают, что значение предоставлено, но реализации базы данных всегда добавляют параметр нулевого значения. Boolean ничем не отличается
MikeT
1
true, на плюсе для вашего метода, если вы правильно сконфигурируете свой номер, он также может быть сохранен в том же байте, что и поле char, что сводит на нет аргумент размера при использовании 0/1, в настоящее время я не могу найти ссылку, но
объем
4
Я подозреваю, что отрицательные голоса связаны с устаревшей точкой зрения на выбор наиболее эффективной реализации памяти. Эта эффективность памяти дня и возраста гораздо менее приоритетна и должна учитываться после удобства использования и совместимости. Всем, кто может ответить на этот комментарий, я рекомендую ознакомиться с преждевременной оптимизацией. Это именно то, что происходит, выбирая «Y / N» исключительно на основе эффективности памяти. Из-за этого решения вы теряете нативную совместимость с набором часто используемых сред.
justin.hughey
5

Либо 1/0, либо Y / N с проверочным ограничением. Эфирный путь в порядке. Лично я предпочитаю 1/0, так как я много работаю в Perl, и это действительно облегчает выполнение логических операций Perl над полями базы данных.

Если вы хотите действительно всесторонне обсудить этот вопрос с одним из оракулов Хонко, посмотрите, что Том Кайт должен сказать по этому поводу. Здесь

Мэтью Уотсон
источник
Говорят, что 1/0 "менее эффективно использует память", но ... мне это тоже нравится больше (а для hibernate очевидно требуется 1/0 для логического значения)
rogerdpack
1/0 - это Hibernate по умолчанию для логического значения, но вы можете определить любое пользовательское сопоставление, которое вам нравится.
Эндрю Спенсер
@rogerdpack, потому что поле char равно 1 байту или 2 байта для nchar, где в зависимости от того, как оно определено, число может быть от 1 до 22 байтов
MikeT
4

База данных, над которой я работал большую часть своей работы, использовала 'Y' / 'N' как логическое значение. С этой реализацией вы можете выполнить некоторые приемы, такие как:

  1. Подсчитайте строки, которые являются истинными:
    ВЫБЕРИТЕ СУММУ (СЛУЧАЙ, КОГДА BOOLEAN_FLAG = 'Y' ТОГДА 1 ИЛИ 0) ОТ X

  2. При группировке строк
    применяйте логику «Если одна строка истинна, тогда все верны»: SELECT MAX (BOOLEAN_FLAG) FROM Y
    И наоборот, используйте MIN для принудительной группировки false, если одна строка ложна.

Эрик Б
источник
4
фактически показанные примеры полезны и для подхода 0/1 - и, ИМХО, быстрее.
igorsantos07
2

Рабочий пример реализации принятого ответа путем добавления столбца «Boolean» в существующую таблицу в базе данных Oracle (с использованием numberтипа):

ALTER TABLE my_table_name ADD (
my_new_boolean_column number(1) DEFAULT 0 NOT NULL
CONSTRAINT my_new_boolean_column CHECK (my_new_boolean_column in (1,0))
);

Это создает новый столбец в my_table_nameвызываемой my_new_boolean_columnсо значениями по умолчанию 0. Столбец не будет принимать NULLзначения и ограничивает принятые значения либо либо, 0либо 1.

Ben.12
источник
1

В наших базах данных мы используем перечисление, которое гарантирует, что мы передадим ему значение ИСТИНА или ЛОЖЬ. Если вы сделаете это одним из первых двух способов, слишком легко либо начать добавлять новое значение к целому числу, не проходя правильную схему, либо заканчивая тем полем char, имеющим Y, y, N, n, T, t, Значения F, f и необходимость запоминания, какой раздел кода использует, какую таблицу и какую версию true она использует.

Райан Ахерн
источник