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


216

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

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


9
Не стесняйтесь спекулировать? Почему-то я не думаю, что это даст вам самый большой набор ответов ..
SCdF

1
Я полагаю, что нет, но я не был уверен, что в этом будет какая-то определенность, поэтому решил, что распахну двери. Кажется, все получилось хорошо, пока.
Крис Р


Ответы:


216

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

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

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

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


60

Том Кайт, вице-президент Oracle:

VARCHAR нулевой длины рассматривается как NULL.

'' не обрабатывается как NULL.

'' когда присваивается символ (1), становится '' (типы символов - пустые строки).

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


17
Ух, Том довольно вялый. Учитывая, что вопросы касаются вопиющего расхождения с SQL92, можно подумать, что он будет менее резок по этому поводу ... хотя, возможно, ему надоело отвечать.
Крис Р

8
Лучшее в Томе - получить четкий ответ, в котором точно указано , что он думает. Посмотрите на некоторые комментарии, в которых люди использовали текст, чтобы поговорить о Спросите Тома
Крис Гилл

9
Но было бы точнее, если бы вторая строка была изменена на '' и не всегда рассматривалась как NULL.
ypercubeᵀᴹ

2
@ypercube Цитата не становится более точной, если изменить слово, которое фактически использует Том. Если ты думаешь, что Том сформулировал это смущающе, ммм. Может быть. Я думаю, что он на месте . Возникает наиболее запутанная ситуация , когда ''в настоящее время неявным преобразуются в VARCHAR2, такие , как , cast('' as char(1)) is nullкоторая ... удивительно ИСТИНА
sehe

1
@sehe запутанный бит для меня это выбрать 1 из двойного где ('' является нулевым)
Мэтт Freake

20

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


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

19

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

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

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

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

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

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


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


2

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

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


Просто установите not nullограничение для вашего столбца и проверяйте только пустую строку.
Егор Скриптунов

6
Проверка обоих условий тривиальна: WHERE Field <> ''возвращает true, только если поле не NULL и не пусто, в базах данных с поведением ANSI для пустых строк.

1

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

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

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

  1. val IS NOT NULL более читабельно, чем val != ''
  2. Не нужно проверять оба условия val != '' and val IS NOT NULL

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

Я согласен с частью сравнения.
Сортировщик

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;

-1

Потому что не рассматривать его как 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 и создал обходной путь - я буду отслеживать свои заметки и публиковать здесь.
Cade Roux

Подробности выложены в виде вопроса здесь.
Cade Roux

-6

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

Пять или шесть лет тому назад Oracle считал, что нулевая строка отличается от нулевой. Хотя, как и ноль, нулевая строка была равна всем и отличалась от всего (что я думаю, хорошо для нулевой, но совершенно НЕПРАВИЛЬНО для нулевой строки), по крайней мере длина (нулевая строка) вернет 0, как и должно быть, так как нулевая строка строка нулевой длины.

В настоящее время в Oracle, длина (ноль) возвращает ноль, что я думаю, это нормально, но длина (нулевая строка) также возвращает ноль, что совершенно НЕПРАВИЛЬНО.

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


Цитирование требуется для проведения различия между «нулевой строкой» и значением NULL. В любой базе данных, кроме Oracle, VARCHARполе может иметь значение (ноль или более символов) или не иметь значения (NULL), полная остановка.

«Пять или шесть лет назад» с 2011 года будет приходиться на 10-граммовый период (10.1 выпущено в 2003 году, 10.2 в 2005 году). 10g абсолютно не внесло каких-либо глобальных изменений в обработку нулей, и никогда не было никакого различия между NULLстрокой с нулевым значением, и такое различие не имеет смысла. Боюсь, этот ответ - полная фантазия.
Уильям Робертсон
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.