Я знаю, что делает рассматривает '' как NULL, но это мало что говорит мне о том, что Почему это так. Насколько я понимаю спецификации SQL, '' - это не то же самое, что NULL - один является действительной датумом, а другой указывает на отсутствие той же информации.
Не стесняйтесь размышлять, но, пожалуйста, укажите, так ли это. Если бы кто-нибудь из Oracle мог это прокомментировать, это было бы здорово!
Думаю, нет, но я не был уверен, что по этому поводу есть определенность, поэтому решил, что распахну двери. Кажется, пока что все получилось хорошо.
Связанный: dba.stackexchange.com/q/49744/56961


Действительно, у меня не было ничего, кроме трудностей в работе с Oracle, включая недопустимые значения даты и времени (не могут быть напечатаны, преобразованы или что-то еще, просто посмотрел с помощью функции DUMP ()), которые позволил должны быть вставлены в базу данных, по-видимому, из-за каких-то ошибок версия клиента в виде двоичного столбца! Вот вам и защита целостности базы данных!
Обработка Oracle ссылок NULL:
http://digitalbush.com/2007/10/27/oracle-9i-null-behavior/
http://jeffkemponoracle.com/2006/02/empty-string-andor-null.html
недопустимые значения времени данных? Не уверен, что это значит. Вы разместили это здесь как вопрос?
Проблема возникла раньше, чем stackoverflow - я не получил полезной информации на форумах Oracle, и я создал обходной путь - я отслежу свои заметки и опубликую здесь.
Выложил подробности в виде вопроса здесь.
Я считаю, что ответ заключается в том, что Oracle очень и очень стара.
Еще в давние времена, до появления стандарта SQL, Oracle приняла проектное решение, согласно которому пустые строки в столбцах VARCHAR / VARCHAR2 являются NULL и что существует только одно значение NULL (есть теоретики относительности, которые будут различать данные, которые никогда не использовались). запрашиваемые данные, ответы на которые существуют, но неизвестны пользователю, данные, на которые нет ответа и т. д., все это составляет некоторое значение NULL).
К тому времени, когда появился стандарт SQL и согласился, что NULL и пустая строка являются отдельными сущностями, уже были пользователи Oracle, у которых был код, предполагавший, что эти две эквивалентны. Таким образом, Oracle в основном оставалась возможность взломать существующий код, нарушить стандарт SQL или ввести какой-то параметр инициализации, который изменил бы функциональность потенциально большого количества запросов. Нарушение стандарта SQL (IMHO) было наименее разрушительным из этих трех вариантов.
Oracle оставила открытой возможность того, что тип данных VARCHAR изменится в будущем выпуске, чтобы соответствовать стандарту SQL (именно поэтому все используют VARCHAR2 в Oracle, поскольку поведение этого типа данных гарантированно останется неизменным в будущем).
Том Кайт вице-президент Oracle:
A ZERO length varchar is treated as NULL.
'' is not treated as NULL.
'' when assigned to a char(1) becomes ' ' (char types are blank padded strings).
'' when assigned to a varchar2(1) becomes '' which is a zero length string and a zero length string is NULL in Oracle (it is no long '')
Вау, Том довольно язвительный. Учитывая, что вопросы относятся к вопиющему расхождению с SQL92, можно подумать, что он будет менее настойчив в этом вопросе ... хотя, возможно, он устал отвечать.
Лучшее в Томе - это то, что вы получаете четкий ответ, в котором точно заявляет, что он думает. Поищите некоторые комментарии, в которых люди использовали текстовые сообщения, на сайте "Спросите Тома"
Но точнее было бы, если бы вторую строку поменяли на '' не всегда обрабатывается как NULL.
@ypercube Цитата не станет более точной, если изменить слово, которое фактически использовал Том. Если вы думаете, что Том сформулировал это запутанно, ммм. Может быть. Я думаю, что он место на. Наиболее запутанные ситуации возникают, когда '' преобразуется косвенно в VARCHAR2, например, cast('' as char(1)) is null, который ... на удивление ИСТИННЫЙ
@sehe сбивающий с толку бит для меня - выбрать 1 из двойного, где ('' равно нулю)
Я ожидаю, что '' не будет рассматриваться как NULL буквальные строки - это символы, а не варчары. Логика. Но почему тогда следующий запрос возвращает ноль строк? select 1 as one from dual where 'a' > '' or 'a' < ''
Поскольку любое сравнение со значением NULL не возвращает ни TRUE, ни FALSE, а UNKNOWN ... и UNKNOWN OR UNKNOWN является UNKNOWN и никогда не будет оправдывать условие where. Вы можете легко проверить это, окружив все свое условие where с помощью NOT (...), и оно все равно даст 0 строк ;-)
@Falco, вокруг которого идет обсуждение '' рассматривается как ноль. Не поведение нулевого значения.
Но если Патрик ожидает, что '' будет рассматриваться как NULL, почему он удивлен, что это ЖЕ поведение, как фактическое значение NULL? Результат его строки будет таким же, независимо от того, помещает ли он туда '' или NULL.
'' is not treated as NULL. Неправильно, на моем Oracle 11.2 следующий код печатает null: if '' is null then SYS.DBMS_OUTPUT.PUT_LINE('null');end if;
@Roland - в контексте он говорил, что '' не рассматривается как нулевой в любой ситуации. В следующей строке приведен пример, когда присвоение его char запускало его поведение пустого заполнения (хотя char также может иметь значение NULL). Я предполагаю, что компилятор PL / SQL следует семантике varchar2, когда встречает нетипизированный ''.
Документация Oracle предупреждает разработчиков об этой проблеме, по крайней мере, до версии 7.
Oracle предпочла представлять NULL методом «невозможного значения». Например, NULL в числовом месте будет сохранен как «минус ноль», невозможное значение. Любые отрицательные нули, полученные в результате вычислений, перед сохранением будут преобразованы в положительный ноль.
Oracle также ошибочно решил считать строку VARCHAR нулевой длины (пустая строка) невозможным значением и подходящим выбором для представления NULL. Оказывается, пустая строка - далеко не невозможное значение. Это даже тождество при операции конкатенации строк!
Документация Oracle предупреждает дизайнеров и разработчиков баз данных о том, что некоторая будущая версия Oracle может разорвать эту ассоциацию между пустой строкой и NULL и разорвать любой код, который зависит от этой ассоциации.
Есть способы пометить NULLS, отличные от невозможных значений, но Oracle их не использовал.
(Я использую слово «местоположение» выше для обозначения пересечения строки и столбца.)
Я подозреваю, что в этом будет больше смысла, если вы подумаете об Oracle так, как, вероятно, думали более ранние разработчики - как о прославленном бэкэнде для системы ввода данных. Каждое поле в базе данных соответствует полю в форме, которую оператор ввода данных видит на своем экране. Если оператор ничего не ввел в поле, будь то «дата рождения» или «адрес», то данные для этого поля «неизвестны». Оператор не может указать, что чей-то адрес на самом деле является пустой строкой, и в любом случае это не имеет особого смысла.
Это имеет смысл только в том случае, если вы предполагаете, что каждое поле в системе ввода данных является обязательным. Отсутствие ответа на необязательное поле (например, «Имя собаки») является допустимым, поэтому пустая строка по-прежнему имеет цель, отличную от NULL. Даже с учетом этого предположения я сомневаюсь, что первые разработчики думали об Oracle как о «прославленном бэкэнде для системы ввода данных», поэтому я не уверен, что этот ответ вообще имеет смысл.
Потому что не рассматривать его как NULL тоже не особо полезно.
Если вы допустили ошибку в этой области в Oracle, вы обычно сразу заметите это. Однако на сервере SQL это будет работать, и проблема возникает только тогда, когда кто-то вводит пустую строку вместо NULL (возможно, из клиентской библиотеки .net, где null отличается от "", но вы обычно относитесь к ним так же ).
Я не говорю, что Oracle прав, но мне кажется, что оба пути примерно одинаково плохи.
Намного, намного проще отлаживать. Кроме того, если вы видите пустую ячейку или ввод на экране, вы знаете, что данные в БД равны нулю. В других БД, где '' <> NULL, вы не можете «увидеть», являются ли данные нулевыми или '', это приводит к очень скрытым ошибкам. '' = null это самый разумный вариант, даже если он нестандартный.
«В других БД, где '' <> NULL, вы не можете« увидеть », являются ли данные нулевыми или ''” => Обычно инструменты БД отображают NULL иначе, чем пустые строки. Фактически, даже Oracle SQL Developer показывает NULL как «(null)». Я предполагаю, что это нужно для того, чтобы отличить NULL от пробелов, но это не связано с разницей между NULL и пустыми строками.
Во-первых, пустые и пустые строки не всегда обрабатывались Oracle как одно и то же. Пустая строка по определению - это строка, не содержащая символов. Это совсем не то же самое, что нуль. NULL по определению означает отсутствие данных.
Пять или шесть лет назад Oracle обрабатывала пустую строку иначе, чем null. Хотя, как и null, нулевая строка была равна всему и отличалась от всего (что, я думаю, нормально для null, но совершенно НЕПРАВИЛЬНО для нулевой строки), по крайней мере length (null string) вернет 0, как и должно быть, поскольку нулевая строка является строка нулевой длины.
В настоящее время в Oracle length (null) возвращает null, что, я думаю, нормально, но length (null string) также возвращает null, что совершенно НЕПРАВИЛЬНО.
Я не понимаю, почему они решили одинаково относиться к этим двум различным «ценностям». Они означают разные вещи, и программист должен иметь возможность действовать по-разному. Тот факт, что они изменили свою методологию, говорит мне, что они действительно не понимают, как следует относиться к этим ценностям.
Цитата, необходимая для проведения различия между «пустой строкой» и значением NULL. В любой базе данных, кроме Oracle, поле VARCHAR может иметь значение (ноль или более символов) или не иметь значения (NULL), точка.
«Пять или шесть лет назад» с 2011 года попадает в временные рамки 10g (10,1 выпущено в 2003 году, 10,2 - в 2005 году). 10g абсолютно не вносил никаких глобальных изменений в обработку нулевых значений, и никогда не было никакого различия между NULL и строкой с нулевым значением, и такое различие не имеет смысла. Боюсь, этот ответ - полная фантазия.
Пустая строка - это то же самое, что NULL, просто потому, что это «меньшее зло» по сравнению с ситуацией, когда две (пустая строка и null) не совпадают.
В языках, где NULL и пустая строка не совпадают, нужно всегда проверять оба условия.
Просто установите ограничение not null для своего столбца и проверяйте только пустую строку.
Проверка обоих условий тривиальна: WHERE Field <> '' возвращает истину, только если поле не равно NULL и не пусто, в базах данных с поведением ANSI для пустых строк.
Согласно официальным документам 11g
Oracle Database currently treats a character value with a length of zero as null. However, this may not continue to be true in future releases, and Oracle recommends that you do not treat empty strings the same as nulls.
Возможные причины
val IS NOT NULL более читабелен, чем val != ''val != '' and val IS NOT NULLВ полностью совместимой с ANSI базе данных вам не нужно проверять оба условия. val <> '' уже исключает NULL. Возможно вы имели в виду val = '' OR val IS NULL. Но пустые строки, которые не сравниваются как NULL, - это полезный!
Я согласен со сравнительной частью.
Пример из книги
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;
Не стесняйтесь размышлять? Почему-то я не думаю, что это даст вам наибольший набор ответов ..