Почему Oracle 9i обрабатывает пустую строку как NULL?

195

Я знаю, что он считает "как" NULL, но это не очень помогает мне объяснить, почему это так. Поскольку я понимаю спецификации SQL, "это не то же самое, что NULL - один является допустимым значением, а другой указывает на отсутствие такой же информации.

Не стесняйтесь спекулировать, но, пожалуйста, укажите, если это произойдет. Если кто-нибудь из Oracle может прокомментировать это, это будет фантастично!

  • 7
    Не стесняйтесь спекулировать? Почему-то я не думаю, что это даст вам самый большой набор ответов ..
  • 1
    Полагаю, нет, но я не был уверен, что в этом будет какая-то определенность, поэтому решил, что распахну двери. Кажется, пока все получилось.
Показать ещё 2 комментария
Теги:
string
null

10 ответов

212
Лучший ответ

Я считаю, что ответ заключается в том, что Oracle очень, очень старый.

В прежние дни, прежде чем появился стандарт SQL, Oracle приняло дизайнерское решение о том, что пустые строки в столбцах VARCHAR/VARCHAR2 были NULL и что было только одно чувство NULL (есть теоретики-реляты который будет различать данные, которые никогда не запрашивались, данные, в которых существует ответ, но неизвестный пользователю, данные, в которых нет ответа, и т.д., все из которых составляют некоторый смысл NULL).

К моменту появления стандарта SQL и согласился, что NULL, а пустая строка - разные сущности, уже были пользователи Oracle, у которых был код, который предположил, что два эквивалента. Таким образом, Oracle в основном остался с вариантами нарушения существующего кода, нарушения стандарта SQL или введения некоторого параметра инициализации, который изменил бы функциональность потенциально большого количества запросов. Нарушение стандарта SQL (IMHO) было наименее разрушительным из этих трех вариантов.

Oracle оставила открытой возможность того, что тип данных VARCHAR изменился в будущей версии, чтобы соответствовать стандарту SQL (поэтому каждый использует VARCHAR2 в Oracle, поскольку такое поведение типа данных гарантировано останется прежним вперед).

54

Tom Kyte VP of Oracle:

Длина длинной длины varchar обрабатывается как NULL.

'' не рассматривается как NULL.

'', когда присваивается значение char (1), становится '' (char пустые пробелы строки).

'' при назначении varchar2 (1) становится '', которая равна нулю строка и нулевая длина строки NULL в Oracle (это не долго)

  • 16
    Ух, Том довольно вялый. Учитывая, что вопросы касаются вопиющего расхождения с SQL92, можно подумать, что он будет менее резок по этому поводу ... хотя, возможно, ему надоело отвечать.
  • 8
    Лучшее в Томе - получить четкий ответ, в котором точно указано , что он думает. Посмотрите на некоторые комментарии, где люди использовали текст, говорите на Спросите Тома
Показать ещё 9 комментариев
18

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

  • 5
    Это имеет смысл, только если вы предполагаете, что каждое поле в системе ввода данных является обязательным. Недопустимый ответ на необязательное поле (например, «Имя собаки») действителен, поэтому пустая строка по-прежнему имеет отличное назначение от NULL. Даже с учетом этого предположения я сомневаюсь, что ранние разработчики считали Oracle «прославленным бэкэндом для системы ввода данных», поэтому я не уверен, что этот ответ имеет смысл вообще.
16

Документация Oracle предупреждает разработчиков об этой проблеме, возвращаясь по крайней мере до версии 7.

Oracle выбрала представление NULLS методом "невозможного значения". Например, NULL в числовом расположении будет сохранен как "минус нуль", значение невозможно. Любые минус-нули, возникающие в результате вычислений, перед сохранением будут преобразованы в положительный ноль.

Oracle также ошибочно решил, что строка VARCHAR с нулевой длиной (пустая строка) является невозможным значением и подходящим выбором для представления NULL. Оказывается, пустая строка далека от невозможного. Это даже тождество при операции конкатенации строк!

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

Существуют методы, чтобы флаг NULLS отличался от невозможных значений, но Oracle их не использовал.

(Я использую слово "location" выше для обозначения пересечения строки и столбца.)

  • 0
    Документация Oracle предупреждает разработчиков и разработчиков баз данных о том, что некоторые будущие версии Oracle могут разорвать эту связь между пустой строкой и NULL и разорвать любой код, который зависит от этой связи. Не могли бы вы предоставить ссылку на это утверждение?
  • 1
    docs.oracle.com/cd/B19306_01/server.102/b14200/...
2

Пустая строка такая же, как NULL, просто потому, что ее "меньшее зло" по сравнению с ситуацией, когда две (пустая строка и нуль) не совпадают.

В языках, где NULL и пустые строки не совпадают, нужно всегда проверять оба условия.

  • 0
    Просто установите not null ограничение для вашего столбца и проверяйте только пустую строку.
  • 5
    Проверка обоих условий тривиальна: WHERE Field <> '' возвращает true, только если поле не NULL и не пусто, в базах данных с поведением ANSI для пустых строк.
0

Пример из книги

   set serveroutput on;   
    DECLARE
    empty_varchar2 VARCHAR2(10) := '';
    empty_char CHAR(10) := '';
    BEGIN
    IF empty_varchar2 IS NULL THEN
    DBMS_OUTPUT.PUT_LINE('empty_varchar2 is NULL');
    END IF;


    IF '' IS NULL THEN
    DBMS_OUTPUT.PUT_LINE(''''' is NULL');
    END IF;

    IF empty_char IS NULL THEN
    DBMS_OUTPUT.PUT_LINE('empty_char is NULL');
    ELSIF empty_char IS NOT NULL THEN
    DBMS_OUTPUT.PUT_LINE('empty_char is NOT NULL');
    END IF;

    END;
0

Согласно официальным документам 11g

В Oracle Database в настоящее время обрабатывается значение символа с нулем как null. Однако в будущих выпусках это не может продолжаться, и Oracle рекомендует не обрабатывать пустые строки так же, как и нули.

Возможные причины

  • val IS NOT NULL более читабельна, чем val != ''
  • Не нужно проверять оба условия val != '' and val IS NOT NULL
  • 4
    В полностью ANSI-совместимой базе данных вам не нужно проверять оба условия. val <> '' уже исключает NULL . Возможно, вы имели в виду val = '' OR val IS NULL . Но пустые строки, которые не сравниваются как NULL, полезны !
0

Потому что не рассматривать его как NULL, не особенно полезно.

Если вы ошибаетесь в этой области в Oracle, вы обычно замечаете сразу. Однако на сервере SQL он работает, и проблема возникает только тогда, когда кто-то вводит пустую строку вместо NULL (возможно, из клиентской библиотеки .net, где null отличается от "", но вы обычно относитесь к ним одинаково).

Я не говорю, что Oracle прав, но мне кажется, что оба способа примерно одинаковы.

  • 2
    Гораздо проще отлаживать. Кроме того, если вы видите пустую ячейку или ввод на экране, вы знаете, что данные в БД пусты. В других БД, где '' <> NULL, вы не можете "видеть", являются ли данные нулевыми или '', это приводит к очень скрытым ошибкам. '' = null это самый разумный вариант, даже если он не стандартный.
  • 2
    «В других БД, где '' <> NULL, вы не можете" видеть ", являются ли данные нулевыми или ''" => Обычно инструменты БД отображают NULL иначе, чем пустые строки. На самом деле, даже Oracle SQL Developer показывает NULL как «(ноль)». Я предполагаю, что это должно отличать NULL от пробела, но это не связано с различием между NULL и пустыми строками.
-6

В действительности, у меня не было ничего, кроме трудностей в работе с Oracle, включая недопустимые значения даты и времени (невозможно напечатать, преобразовать или что-либо еще, просто посмотреть с помощью функции DUMP()), которые разрешены быть вставлен в базу данных, по-видимому, через какую-то ошибочную версию клиента как двоичный столбец! Так много для защиты целостности базы данных!

Обработка Oracle ссылок NULL:

http://digitalbush.com/2007/10/27/oracle-9i-null-behavior/

http://jeffkemponoracle.com/2006/02/empty-string-andor-null.html

  • 1
    неверные значения времени данных? Не уверен, что это значит. Вы разместили это как вопрос здесь?
  • 1
    Эта проблема возникла ранее, из-за переполнения стека - я не получил никакой полезной информации с форумов Oracle и создал обходной путь - я буду отслеживать свои заметки и публиковать здесь.
Показать ещё 1 комментарий
-7

Прежде всего, нулевая и нулевая строка не всегда считались Oracle одинаковыми. Нулевая строка - по определению строка, не содержащая символов. Это совсем не то же самое, что и null. NULL является, по определению, отсутствием данных.

Пять или шесть лет назад нулевая строка обрабатывалась Oracle по-разному от нуля. Хотя, как и null, нулевая строка была равна всем и отличается от всего (что, я думаю, подходит для null, но полностью WRONG для пустой строки), по крайней мере длина (пустая строка) вернет 0, как и должно быть, поскольку нулевая строка строка нулевой длины.

В настоящее время в Oracle длина (null) возвращает значение null, которое, как я полагаю, является O.K., но length (null string) также возвращает null, что полностью НЕПРАВИЛЬНО.

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

  • 0
    Цитирование требуется для проведения различия между «нулевой строкой» и значением NULL. В любой базе данных, кроме Oracle, поле VARCHAR может иметь значение (ноль или более символов) или не иметь значения (NULL), полная остановка.
  • 0
    «Пять или шесть лет назад» с 2011 года будет приходиться на 10-граммовый период (10.1 выпущено в 2003 году, 10.2 в 2005 году). 10g абсолютно не внесло каких-либо глобальных изменений в обработку нулей, и никогда не было никакого различия между NULL и строкой с нулевым значением, и такое различие не имеет смысла. Боюсь, этот ответ - полная фантазия.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню