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 хранит данные (взятые из документация):

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, чтобы умереть.

Ответ 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