Булеве поле в 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.