Oracle не различает нули и пустые строки?
По-видимому, оракул, похоже, не различает пустые строки и нули. Например.
Select name from TABLE_A where id=100;
ID NAME
100 null
Update TABLE_A set NAME='' where id=100;
SELECT -->
ID NAME
100 null
SELECT length(NAME) FROM TABLE_A WHERE id=100;
null
Я не могу придумать какой-либо веской причины, по которой Oracle будет построен, чтобы вести себя таким образом (это делает это и в sqlplus?) Я получаю доступ через интерфейс java, ссылка на статью используется клиентом php).
Разве вы не хотели бы отличить длину 0 от длины undefined? Это известная проблема? Преднамеренное поведение для определенной цели? Долгосрочный спор в теории баз данных? Что дает?
(Это было вызвано Мэттом Солнитом на этот вопрос.)
Ответы
Ответ 1
Oracle
очень очень старый.
Вернувшись в 80's
, когда он был разработан (и до того, как были какие-то стандарты), они думали, что это хорошая идея, и учитывая, что Oracle
сохраняет свои значения, это действительно так.
Здесь Oracle
хранит данные (взятые из документация):
![How Oracle stores data alt text]()
В данных не сохраняется тип данных, а только длина данных и сами данные.
Если NULL
происходит между двумя столбцами со значениями, он хранится как однобайтовый столбец значения имеет длину 0
(фактически, 0xFF
). Трейлинг NULL
не сохраняется вообще.
Итак, чтобы сохранить значение 'test'
, Oracle
необходимо сохранить 5 байтов: 04 74 65 73 74
.
Однако для хранения как пустой строки, так и NULL
, Oracle
просто нужно установить длину данных на 0
.
Очень умный, если ваши данные должны храниться на жестких дисках 20 Mb
, стоимость которых стоит 5,000$
.
Позже, когда появились стандарты, это уже не было такой хорошей идеей, но к тому времени уже было много и много кода, основанных на NULL
и ''
. Это одна и та же вещь.
Создание VARCHAR
для такого различия приведет к разрыву тонн кода.
Чтобы исправить это, они переименовали VARCHAR
в VARCHAR2
(который не является частью какого-либо стандарта), заявил, что VARCHAR2
будет никогда проводить различие между NULL
и пустым и настоятельно призывал всех использовать этот тип данных.
Теперь они, вероятно, ждут последнего человека, который использовал VARCHAR
в Oracle
, чтобы умереть.
Ответ 2
Возможно, вы захотите прочитать эту длинную и порой забавную дискуссию об этом точном предмете более двух лет назад в OTN: http://forums.oracle.com/forums/thread.jspa?threadID=456874&start=0&tstart=0
С уважением,
Роб.
Ответ 3
Вот почему умные люди вроде Date говорят, что вы НИКОГДА не должны использовать нули.
(Нет, я должен быть точным. Фактически это всего лишь одна из почти сотен причин, о которых он упомянул за последние несколько десятилетий, чтобы поддержать это утверждение.)
ИЗМЕНИТЬ
Я также хотел бы ответить на это:
"Создание VARCHAR для такого разграничения приведет к разрыву тонны кода".
Да, и конечно, нарушая хотя бы дух стандарта, заменяя "пустую строку" нулевым значением на каждое обновление, является меньшим злом?
(Примечание: null не равно никому, даже самому себе, поэтому после назначения пустой строки столбцу oracle даст вам значение в этом столбце, который НЕ совпадает с значением, которое вы сказали, что хотите там. Вау.)
Ответ 4
Похоже, Oracle заявила, что это поведение может быть изменено в будущей версии. Когда и какой выпуск он будет, не упоминается.
Если у вас есть доступ к metalink, обратите внимание: 1011340.6 (к сожалению, из-за ограничений я не могу скопировать содержимое примечания здесь)
Если у вас нет доступа к metalink, тогда посмотрите на следующую документацию по выпуску 10g здесь
Ответ 5
@Ian, ответ вам.
Триггеры Oracle могут ссылаться на таблицу, в которой они созданы:
create table t (id number(10) );
create or replace trigger t_bir before insert on t for each row
declare
l_id t.id%type;
begin
select id
into l_id
from t
where id = :new.id;
exception
when no_data_found then
null;
end;
/
SQL> insert into t values (20);
1 row is created.
SQL> select * from t;
ID
----------
20