Отсутствие в Oracle типа данных Bit для столбцов таблицы - PullRequest
26 голосов
/ 11 марта 2010

Я работаю разработчиком в небольшой команде разработчиков, и что-то раздражает меня до такой степени, что я решил действовать ...

Oracle не поддерживает битовый тип данных или что-то еще, что имеет очевидный смысл в сценариях true / false. Однако, до того как я присоединился к команде, мои предки решили использовать вместо этого поля char (1), используя специальную букву для обозначения yes / true. К сожалению, наше приложение используется людьми во всем мире, и по причинам, которые откровенно игнорируют все мои попытки понять, используемая ценность варьируется в зависимости от локализации.

Да, я знаю, что это совершенно не нужно для значений в серверной части, которые пользователь никогда не видит - однако ...

Я заметил, что эта практика, похоже, переносится в новую разработку, что меня бесит - поэтому я думаю предложить вместо этого Число (1,0) - 0 считается ложным / нет, все что угодно иначе истолковывается как правда / да ...

Простой вопрос - может кто-нибудь придумать причину, по которой это может быть плохой идеей?

Пока мы об этом, кто-нибудь знает, почему Oracle не поддерживает простой логический тип? Разве это не слепое опущение?

Приветствия в ожидании,

Martin.

Ответы [ 9 ]

27 голосов
/ 11 марта 2010

Используйте CHAR (1) и ограничение, чтобы разрешить только «1» и «0».

...

col CHAR(1),
CONSTRAINT cons_atable_col1 CHECK (col1 IN ('1','0'))
16 голосов
/ 11 марта 2010

Я не англичанин, поэтому я склонен использовать 1 и 0 или '1' и '0'. Использование 'Y' и 'N' не имеет смысла, если вы не пишете на английском языке (да, кодирование на родном языке существует). Использование 'SI' и 'NO' или 'S' и 'N' не выглядит профессионально (так же, как именование переменных буквами с акцентом). Единицы и нули, наоборот, довольно стандартны, если вы кодировали на C, PHP или JavaScript. В любом случае я всегда добавляю соответствующее ограничение, чтобы запретить любой другой символ. Помимо субъективных проблем, я не думаю, что при выборе CHAR или NUMBER заметно повышение производительности. Я люблю цифры немного больше, потому что мне не нужно их цитировать:)

Я согласен, что это явное упущение, но я читал очень горячие дискуссии на эту тему на некоторых форумах Oracle; это своего рода религиозная проблема. Некоторые утверждают, что логические значения принадлежат к типам данных приложения и не имеют места в ядре базы данных. Честно говоря, я верю, что это один из тех, кого мы так долго обходились без него, что нам лучше было сказать, что это было нарочно.

Кстати, MySQL имеет тип BOOLEAN, но это синоним TINYINT (1), поэтому в конечном итоге он равен 1 и 0; это нормально, потому что он также имеет константы TRUE и FALSE, которые оцениваются в 1 и 0.

11 голосов
/ 11 марта 2010

Я предпочитаю char (1), а не число (1), поскольку при некотором разумном выборе символов очевидно, какой символ имеет какое булево значение.

Конечно, вы должны бороться со всеми различными вариациями, выбрать один и убедиться, что он используется, установив проверочные ограничения на столбцы.

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

И, конечно, это явное замечание. Что еще хуже, PL / SQL имеет логическое значение, но вы не можете использовать его в операторах SQL.

8 голосов
/ 11 марта 2010

Вот Спросите Тома обсуждение по теме. Предоставляет ориентированный на Oracle взгляд на проблему.

Что касается хранения, char (1) на самом деле немного (без каламбура) более эффективен:

SQL> CREATE TABLE xx (c CHAR(1), n NUMBER);

Table created

SQL> insert into xx values('T', 1);

1 row inserted

SQL> select dump(c), dump(n) from xx;

DUMP(C)             DUMP(N)
------------------- -------------
Typ=96 Len=1: 84    Typ=2 Len=2: 193,2
3 голосов
/ 08 июня 2015

Согласно этому руководству по Oracle - вы должны использовать NUMBER (3). Сумасшедший, но правда.

http://docs.oracle.com/cd/B19306_01/gateways.102/b14270/apa.htm

2 голосов
/ 11 марта 2010

Число (1) не лучше чем символ (1). Особенно, если это будет в дополнение к существующему символу (1). Это только добавит путаницы.

FWIW, Oracle во внутренних представлениях (например, USER_TAB_COLUMNS) использует varchar2 (3) (YES и NO). Однако не уверен, что они соответствуют на 100%.

0 голосов
/ 15 октября 2016

Oracle внутренне использует «биты» (а не тип данных как таковой) в разных представлениях словаря данных.

Например, представление dba_users имеет:

..
        , DECODE (BITAND (u.spare1, 128), 128, 'YES', 'NO')
..
        , DECODE (BITAND (u.spare1, 256), 256, 'Y', 'N')
..

, который показывает способ обойти это в некотором роде. Если вам не нужно часто изменять «логические» биты, вы можете использовать тот же подход, что и Oracle, начиная с Oracle 6 (по крайней мере). Создайте таблицу со столбцом NUMBER и VIEW поверх того, что скрывает сложность операций BITAND.

пс. С другой стороны, Oracle JDBC имеет битовый тип данных https://docs.oracle.com/cd/E16338_01/appdev.112/e13995/oracle/jdbc/OracleTypes.html#BIT, а вы уже знаете, что PL / SQL имеет логический тип. Хотя это, вероятно, не очень вам поможет. См. Подход BITAND выше, если он подходит вашему делу.

0 голосов
/ 23 июля 2015

https://docs.oracle.com/cd/E17952_01/refman-5.5-en/char.html enter image description here

Как сказал DCookie, char (1) более эффективен. Поскольку VARCHAR2 (VARCHAR) empty содержит 1 байт, но когда мы сохраняем 1 символ, тогда пустой 1 байтовый размер + с символом 1 байтовый размер -> 2 байта должен хранить 1 символ в varchar

0 голосов
/ 18 марта 2015

Вопрос старый, но до тех пор, пока не будет использован последний выпуск oracle, он все еще остается действительным.

Я бы решил проблему следующим образом: Создайте таблицу, которая содержит возможные значения для true / false плюс локализованный отображаемый текст f.e. T $ KEYWORDS ITEMNO ITEMTEXT ITEMTEXT_DE ITEMTEXT_FE ... 0 Ложный Фальш 1 True Wahr

Вместо Истина / Ложь также может быть выбрано, не выбрано и т. Д.

А затем добавьте передний ключ к вашему столбцу в этой таблице. Таким образом, у вас есть только допустимые значения, и они не меняются при локализации.

Еще одно хорошее решение imho - использовать проверочное ограничение для вашего столбца данных. Это правило не работает, если ваши значения могут быть разными в одной и той же базе данных / столбце в зависимости от локализации клиентов.

alter table tblLocations add flag number CONSTRAINT <constraintname> CHECK (flag IN (1,0));

...