Соответствует ли эта реализация SQL-92? - PullRequest
5 голосов
/ 20 января 2009

Тони Эндрюс в другом вопросе привел пример:

IF p_c_courtesies_cd 
   || p_c_language_cd 
   || v_c_name 
   || v_c_firstname 
   || v_c_function 
   || p_c_phone 
   || p_c_mobile p_c_fax 
   || v_c_email is not null
THEN
     -- Do something
END IF;

как умная (если не совсем непонятная) альтернатива функции Oracle COALESCE. Конечно же, это работает, если какой-либо аргумент не является нулевым, тест IF является истинным. Мой вопрос: соответствует ли реализация Oracle вышеупомянутой операции конкатенации SQL-92? Разве выражение с участием NULL не должно оцениваться как NULL? Если вы так не думаете, то почему выражение 1 + NULL должно оцениваться как NULL?

Ответы [ 5 ]

3 голосов
/ 21 января 2009

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

Все начинается с того факта, что Oracle хранит строки с количеством символов, за которым следуют строковые данные. NULL представлен нулевым количеством символов без следующих строковых данных, что в точности совпадает с пустой строкой (''). У Oracle просто нет способа их различить.

Это приводит к некоторому странному поведению, такому как этот случай объединения. В Oracle также есть функция LENGTH, которая возвращает длину строки, но это было определено противоположным образом, поэтому LENGTH ('') возвращает NULL, а не ноль. Итак:

LENGTH('abc') + LENGTH('') IS NULL

LENGTH('abc' || '') = 3

что мне кажется нарушающим основные математические принципы.

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

2 голосов
/ 20 января 2009

@ Незрой: Спасибо за ссылку. Однако, когда я читаю стандарт, я полагаю, что он утверждает, что реализация Oracle на самом деле неверна. Раздел 6.13, Общие правила, пункт 2а:

     2) If <concatenation> is specified, then let S1 and S2 be the re-
        sult of the <character value expression> and <character factor>,
        respectively.

        Case:

        a) If either S1 or S2 is the null value, then the result of the
          <concatenation> is the null value.
1 голос
/ 20 января 2009

На основании части спецификации SQL-92 , выделенной DCookie, и поведения других БД, я бы сказал, что Oracle не соответствует стандарту с их оператором конкатенации.

Оракул (из ответа Туинстоуля):

SQL>  select 'something'||null from dual;

'SOMETHIN
---------
something

MSSQL:

SELECT 'something'+NULL;

NULL

PostgreSQL:

postgres=# \pset null '(null)'
Null display is "(null)".
postgres=# select 'something'||null as output;
 output
--------
 (null)
(1 row)

MySQL:

mysql> select concat('something',NULL) as output;
+--------+
| output |
+--------+
| NULL   |
+--------+
1 row in set (0.00 sec)
1 голос
/ 20 января 2009

Ну, COALESCE явно определяется стандартом SQL-92 для возврата первого значения, отличного от NULL, в списке; так что по определению реализация Oracle ведет себя правильно.

РЕДАКТИРОВАТЬ: SQL-92 spec ; найдите COALESCE, чтобы увидеть его определение.

Тем не менее, нет ничего конкретного в NULL, в котором говорится, что любая операция с участием NULL должна быть NULL. Более точное ограничение заключается в том, что NULL не является ни ложным, ни 0, ни равным другому NULL (например, NULL == NULL является ложным, поскольку один NULL не равен другому NULL). Однако это не означает, что не может быть логически согласованных способов работы с NULL, которые не всегда возвращают NULL.

РЕДАКТИРОВАТЬ: Таким образом, NULL + 1 равен NULL так же, как NaN + 1 по-прежнему NaN; это фактически неопределенная операция.

0 голосов
/ 20 января 2009
SQL>  select 'something'||null from dual;

'SOMETHIN
---------
something

конкатенация строк с нулем не приводит к нулю. Я думаю, что это нормальное поведение, я привык к этому. Не знаю, что еще сказать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...