Это не то, что вы не знаете, что убьет вас. Это «то, что вы знаете», что просто не так ...
Причина, по которой Oracle не рассматривает ''
как NULL, заключается в том, что ''
не является NULL - это ноль- длина строки константа. Теперь, прямо здесь люди собираются заскочить и сказать мне, что я неправ, и что я не знаю, о чем говорю, и поставить под сомнение мое происхождение, и, вероятно, начать ходатайство об отказе в моем социальном обеспечении и пнуть меня из дома старого пуканья, но я прав. Вот демонстрация:
DECLARE
vStr VARCHAR2(10) := '';
cStr CHAR(10) := '';
vNULL VARCHAR2(10) := NULL;
cNULL CHAR(10) := NULL;
nStr NUMBER := '';
nNULL NUMBER := NULL;
BEGIN
DBMS_OUTPUT.PUT_LINE('LENGTH(vStr) = ' || LENGTH(vStr));
DBMS_OUTPUT.PUT_LINE('LENGTH(cStr) = ' || LENGTH(cStr));
DBMS_OUTPUT.PUT_LINE('LENGTH(vNULL) = ' || LENGTH(vNULL));
DBMS_OUTPUT.PUT_LINE('LENGTH(cNULL) = ' || LENGTH(cNULL));
DBMS_OUTPUT.PUT_LINE('LENGTH(nStr) = ' || LENGTH(nStr));
DBMS_OUTPUT.PUT_LINE('LENGTH(nNULL) = ' || LENGTH(nNULL));
END;
Теперь , не глядя вниз (да, я знаю - это сложно. Попробуйте ... :-) Какой вывод вы ожидаете от приведенного выше кода? Если вы похожи на большинство людей (включая меня, пока я не споткнулся об этом несколько лет go), вы ожидаете, что это будет:
LENGTH(vStr) =
LENGTH(cStr) =
LENGTH(vNULL) =
LENGTH(cNULL) =
LENGTH(nStr) =
LENGTH(nNULL) =
То есть вы ожидаете LENGTH
функция, возвращающая NULL, когда применяется ко всем этим переменным - потому что все они должны быть NULL, верно?
Но это не то, что вы получаете ( см. Эту базу данных <> fiddle ). То, что вы на самом деле получаете:
LENGTH(vStr) =
LENGTH(cStr) = 10
LENGTH(vNULL) =
LENGTH(cNULL) =
LENGTH(nStr) =
LENGTH(nNULL) =
Вау! Подождите!! Что там делает 10
?!?
Ну, это довольно просто. Подумайте о семантике типа данных CHAR
в PL / SQL. Если вы назначаете строку переменной или полю CHAR
, а длина назначенной строки короче определенной длины переменной или поля, значение, назначенное переменной или полю, дополняется справа до полного определенного ширина переменной / поля - в данном случае 10 символов. Поэтому, когда ''
- то есть строковая константа нулевой длины - назначается переменной cStr
, значение, назначенное переменной, дополняется справа до определенной ширины переменной, поэтому cStr
заканчивается заполнен 10 пробелами. Но когда NULL присваивается той же символьной переменной, в конечном итоге устанавливается значение NULL, как и ожидалось, и функция LENGTH
возвращает NULL, как и ожидалось.
Семантика VARCHAR2 (и на данный момент , VARCHAR - по крайней мере, до тех пор, пока Oracle не найдет поддержку семантики ANSI для VARCHAR - что они собираются сделать в настоящий момент (tm)) различаются в Oracle. Когда переменной / полю типа VARCHAR2 присваивается значение, оно не выполняет никаких дополнений; вместо этого он присваивает переменной или полю только значащие символы исходной строки, и если результирующая длина строки, назначенной переменной, равна нулю, тогда для переменной или поля устанавливается значение NULL в соответствии с правилом Oracle что «строковые значения нулевой длины совпадают с NULL». Но это происходит в тот момент, когда значение присваивается переменной. ''
само по себе все еще является строковой константой нулевой длины.
Просто помните - это не то, что вы не знаете, что убьет вас. Это "то, что ты знаешь", но это не так ...: -)