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


145

Вчора я хотів додати булеве поле до таблиці Oracle. Однак насправді булового типу даних в Oracle насправді немає. Хтось тут знає найкращий спосіб імітувати булів? Гугл предмету виявив кілька підходів

  1. Використовуйте ціле число і просто не турбуйтеся призначаючи йому нічого, крім 0 або 1.

  2. Використовуйте поле char із "Y" або "N" як єдиних двох значень.

  3. Використовуйте enum із обмеженням CHECK.

Чи знають досвідчені розробники Oracle, який підхід є кращим / канонічним?


195
Я хотів би, щоб Oracle мав wallтип даних, щоб я міг бити голову об нього під час використання булів.
Грег

Відповіді:


82

Я вважаю це посилання корисним.

Ось параграф, який висвітлює деякі плюси та мінуси кожного підходу.

Найпоширеніший дизайн - це наслідування багатьох булевих прапорів, якими користуються перегляди словника даних Oracle, вибираючи "Y" для істинного та "N" для хибного. Однак, щоб правильно взаємодіяти з хост-середовищами, такими як 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);`

31
Я не рекомендую використовувати "N" та "Y", оскільки це залежить від мови. Англофони іноді забувають, що більша частина світу не представляє поняття істини буквою Y. Навпаки, значення 0 і 1 є постійним через мовні бар'єри.
Ендрю Спенсер

7
0 і 1 як булеві значення не відповідають стандартам інформатики - у мов типу скриптів оболонки, як правило, 0 як успіх, а ненульове - як відмова, тоді як у мовах типу C, як правило, 0 як невдача, а ненульове - як успіх.
Філ

41
Як булеві значення вони неоднозначні. Коди повернення процесу не булеві значення.
Ендрю Спенсер

13
Чому весь цей абзац із наданого посилання був проігнорований у цій відповіді? "Найпоширеніший дизайн - це імітувати безліч булевих подібних прапорів, якими користуються перегляди словника даних Oracle, вибираючи" Y "для істинного та" N "для хибного. Однак, щоб правильно взаємодіяти з середовищами господарів, такими як JDBC, OCCI, та інших програмних середовищ, краще вибрати 0 для помилкових та 1 для істинних, щоб він міг правильно працювати з функціями 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 як ЗАРІБ для просторової ефективності, але це для мене трохи закручено), використовуючи NOT NULL і обмеження перевірки, щоб обмежити вміст цими значеннями. (Якщо вам потрібно, щоб стовпчик був нульовим, то це не булева ситуація, з якою ви маєте справу, а перерахування з трьома значеннями ...)

Переваги 0/1:

  • Мова незалежна. "Y" і "N" було б добре, якби всі користувалися ним. Але вони цього не роблять. У Франції вони використовують "O" і "N" (я це бачив на власні очі). Я не програмував у Фінляндії, щоб побачити, чи вони там використовують "E" і "K" - без сумніву, вони розумніші за це, але ви не можете бути впевнені.
  • Погоджується з практикою широко використовуваних мов програмування (C, C ++, Perl, Javascript)
  • Краще грає з шаром програми, наприклад, в сплячому режимі
  • Приводить, наприклад, більш лаконічний 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" / null для підвищення продуктивності. Якщо ви довели, що вам потрібна продуктивність, то досить справедливо, але в іншому випадку уникайте, оскільки це робить запит менш природним ( some_column is nullзамість some_column = 0), а в лівому приєднанні ви будете суперечити помилковості з неіснуючими записами.


3
Ви виявляєте, що в наші дні багато булів є TriState, тобто правда, помилка та невідомість. що ідеально відповідає нульовій ідеї бази даних. просто тому, що багато разів, не знаючи жодної відповіді, життєво важливо
MikeT

1
Так, справжнє-хибне-невідоме може вимагатись, хоча якби я був прискіпливим (яким я є), я б сказав, що насправді його не слід називати булевим, оскільки це не так.
Ендрю Спенсер

2
якщо ви будете такими вибагливими, то ви можете зробити один і той же аргумент для кожного типу даних. так як під суворим визначенням ціле, подвійне (я думаю, я повинен сказати подвійну довжину двійки доповнюють плаваючою точкою), двійкові, рядки тощо, всі припускають, що значення надається, але реалізація бази даних завжди додає параметр "нульове значення" Булевий не відрізняється
MikeT

1
правда, на замітку плюс для вашого методу, якщо ви правильно налаштували свій номер, його також можна зберігати в тому ж байті, що і поле char, яке зводить нанівець аргумент розміру проти використання 0/1, я не можу знайти посилання на даний момент, але об'єм пам’яті для числа становить від 1 до 22 байт залежно від конфігурації
MikeT

4
Я підозрюю, що голосування внаслідок старого погляду на вибір найбільш ефективної пам’яті реалізації. Ця ефективність пам’яті для денного та вікового періоду є далеко не пріоритетною, і її слід враховувати після зручності використання та сумісності. Всім, хто може відповісти на цей коментар, рекомендую ознайомитися з достроковою оптимізацією. Саме це і відбувається, вибираючи "Y / N" виключно на основі ефективності пам'яті. Через це рішення ви втрачаєте натисну сумісність із набором часто використовуваних рамок.
Justin.hughey

5

1/0 або Y / N із обмеженням чека. ефірний спосіб прекрасний. Я особисто віддаю перевагу 1/0, оскільки я роблю багато роботи в perl, і це робить дуже просто робити Perl Boolean операції на полях баз даних.

Якщо ви хочете дійсно в поглибленому обговоренні цього питання з одним з голови босів оракулів, перевірити, що Том Кайт повинен сказати про це тут


Кажуть, що 1/0 є "менш ефективною пам'яттю", але ... мені це теж подобається (і в сплячому режимі, мабуть, потрібен 1/0 для булевого)
rogerdpack

1/0 - типовий режим Hibernate для булевого, але ви можете визначити будь-яке спеціальне відображення, яке вам подобається.
Ендрю Спенсер

@rogerdpack thats тому, що поле char - 1 байт, або 2 байти для nchar, де залежно від того, як визначено число, може бути від 1 до 22 байт
MikeT

4

База даних, яку я робив більшу частину своєї роботи, використовувала "Y" / "N" як булеві. З цією реалізацією ви можете вирішити деякі хитрощі, як-от:

  1. Підрахуйте рядки, що відповідають дійсності:
    ВИБІРТЕ СУМУ (СЛУЧАЙ КОЛИ BOOLEAN_FLAG = 'Y' ТОЖ 1 ELSE 0) ВІД X

  2. При групуванні рядків
    застосуйте логіку "Якщо один рядок є істинним, то всі істинні" логікою: SELECT MAX (BOOLEAN_FLAG) FROM Y
    І навпаки, використовуйте MIN, щоб змусити групування помилковим, якщо один рядок false.


4
насправді наведені приклади також корисні для підходу 0/1 - і, IMHO, швидше.
igorsantos07

2

Робочий приклад для реалізації прийнятої відповіді, додавши стовпчик "Булева" до існуючої таблиці в базі даних 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.


1

У наших базах даних ми використовуємо enum, який гарантує, що ми передаємо його ІСТИНО, або ЛЖО. Якщо зробити це будь-яким із перших двох способів, надто просто або почати додавати нове значення в ціле число, не проходячи належну конструкцію, або закінчившись цим полем char, яке має Y, y, N, n, T, t, Значення F, f і необхідно пам'ятати, який розділ коду використовує таблицю та яку версію true використовує.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.