代码之家  ›  专栏  ›  技术社区  ›  DCookie

此实现是否符合SQL-92?

  •  5
  • DCookie  · 技术社区  · 17 年前

    Tony Andrews 在另一个 question 举例说明:

    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;
    

    作为OracleCalesce函数的一个聪明(如果不是有点晦涩)的替代方案。当然,它是有效的,如果任何参数不是空的,那么if测试是真的。我的问题是:Oracle对上述连接操作SQL-92的实现是否符合要求?涉及空值的表达式不应计算为空值吗?如果您不这么认为,那么为什么表达式1+null的计算结果应该为空?

    5 回复  |  直到 17 年前
        1
  •  3
  •   Tony Andrews    17 年前

    不,Oracle对空值的处理是特殊的,与其他人的不同,并且与ANSI标准不一致。然而,在甲骨文的辩护中,在有一个与之一致的美国国家标准协会标准之前,它可能已经决定并致力于这种治疗。

    这一切都是从这样一个事实开始的:Oracle存储的字符串的字符数后跟字符串数据。空的字符计数为零,没有后续的字符串数据-与空字符串(“”)完全相同。甲骨文根本没有办法区分它们。

    这会导致一些奇怪的行为,比如这个串联案例。Oracle还具有返回字符串长度的函数长度,但这是以相反的方式定义的,因此长度(“”)返回空值而不是零。所以:

    LENGTH('abc') + LENGTH('') IS NULL
    
    LENGTH('abc' || '') = 3
    

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

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

        2
  •  2
  •   DCookie    17 年前

    @纳兹罗伊:谢谢你的链接。然而,当我阅读该标准时,我相信它指出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.
    
        3
  •  1
  •   nezroy    17 年前

    well coalesce由SQL-92标准显式定义,以返回列表中的第一个非空值;因此,根据定义,它的Oracle实现运行正常。

    编辑: SQL-92 spec ;搜索coalesce以查看其定义。

    也就是说,对于空值没有具体的说明,任何涉及空值的操作都必须为空。更确切的限制是,空值既不为假也不为0,也不等于另一个空值(例如,空值==null为假,因为一个空值不等于另一个空值)。然而,这并不意味着,仍然不能有逻辑上一致的方法来处理不总是返回空值的空值。

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

        4
  •  1
  •   nezroy    17 年前

    基于 SQL-92 由dcookie和其他DBS的行为突出显示的规范,我想说Oracle的行为不符合其连接操作符的标准。

    Oracle(摘自Tuinstoel的回答):

    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)
    
        5
  •  0
  •   tuinstoel    17 年前
    SQL>  select 'something'||null from dual;
    
    'SOMETHIN
    ---------
    something
    

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