5

Tony Andrews在另一个问题中举了一个例子:

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?

4

5 回答 5

3

不,Oracle 对空值的处理是特殊的,与其他所有人的不同,并且与 ANSI 标准不一致。然而,在甲骨文的辩护中,它可能早在 ANSI 标准出现之前就已经确定并致力于这种处理方式!

这一切都始于 Oracle 存储带有字符数的字符串,然后是字符串数据。NULL 由零字符数表示,没有后续字符串数据 - 这与空字符串 ('') 完全相同。Oracle 根本没有办法区分它们。

这会导致一些古怪的行为,例如这种串联情况。Oracle 也有一个函数 LENGTH 来返回字符串的长度,但这是以相反的方式定义的,因此 LENGTH('') 返回 NULL 而不是零。所以:

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

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

在我看来,这违反了基本的数学原理。

当然,Oracle 开发人员已经习惯了这一点,以至于我们中的许多人甚至看不出它有任何错误或奇怪之处——事实上,有些人会争辩说世界其他地方都是错误的,空字符串和 NULL相同的事物!

于 2009-01-21T11:06:39.337 回答
2

@Nezroy:感谢您的链接。然而,当我阅读该标准时,我相信它表明 Oracle 的实现实际上是不正确的。第 6.13 节,一般规则,第 2a 项:

     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.
于 2009-01-20T19:15:29.893 回答
1

那么 COALESCE 是由 SQL-92 标准明确定义的,用于返回列表中的第一个非 NULL 值;所以根据定义,Oracle 的实现是正确的。

编辑:SQL-92 规范;搜索 COALESCE 以查看其定义。

也就是说,关于 NULL 没有任何具体的规定,即任何涉及 NULL 的操作都必须为 NULL。更准确的限制是 NULL 既不为假也不为 0 也不等于另一个 NULL(例如 NULL == NULL 为假,因为一个 NULL 不等于另一个 NULL)。然而,这并不意味着仍然不能有逻辑一致的方式来处理不总是返回 NULL 的 NULL。

编辑:所以 NULL + 1 是 NULL,就像 NaN + 1 仍然是 NaN 一样;它实际上是一个未定义的操作。

于 2009-01-20T18:35:06.013 回答
1

基于 DCookie 突出显示的SQL-92规范部分和其他数据库的行为,我想说 Oracle 的连接运算符的行为不符合标准。

甲骨文(来自 tuinstoel 的回答):

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

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

微软SQL:

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)
于 2009-01-20T20:06:19.683 回答
0
SQL>  select 'something'||null from dual;

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

与 null 的字符串连接不会导致 null。我认为这是正常的行为,我已经习惯了。不知道还能说什么。

于 2009-01-20T18:46:24.167 回答