如何在SQL中使用类似C#的行为进行等式比较?

Hao*_*Hao 5 c# sql compare equality

如何比较SQL中的值的等价与null?

对于熟悉C#的人,以下是比较可空值的结果:

null == null : true
null == john : false
null == paul : false
john == null : false
john == john : true
john == paul : false
paul == null : false
paul == john : false
paul == paul : true
Run Code Online (Sandbox Code Playgroud)

我在SQL中找到的最简单的解决方案是将可空字段合并为一些sentinel值(例如'scoobydoo')然后比较它们

coalesce(A, 'scoobydoo') = coalesce(B, 'scoobydoo')
Run Code Online (Sandbox Code Playgroud)

但是,如果有人使用sentinel值,那么这就是普通的kludge,如果A恰好是NULL而B是'scoobydoo',那么上面的表达式会产生真值

这正是我要求上面代码逻辑的目的(T-SQL UPDATE触发器):

-- detect if the value changes

if (select invoice_date from inserted) <> 
   (select invoice_date from deleted) begin

    -- do something to summary tables here

end
Run Code Online (Sandbox Code Playgroud)

如何在SQL中使用类似C#的行为进行等式比较?

[编辑:在这里找到答案]

测试了代码(Postgres很好的布尔支持,FTW!):

select

    A, B,

    A = B,
    A IS NOT DISTINCT FROM B, -- "logically" same as above

    A <> B,
    A IS DISTINCT FROM B -- "logically" same as above

from(    
    values
    (null, null),
    (null, 'john'),
    (null, 'paul'),
    ('john', null),
    ('john', 'john'),
    ('john', 'paul'),
    ('paul', null),
    ('paul', 'john'),
    ('paul', 'paul')) as x(A,B)
Run Code Online (Sandbox Code Playgroud)

[编辑:测试了Jon的代码,他对平等各种半工作的回答(无论如何只是将null视为假),但他对不平等的回答是炸弹的]

测试了代码(Postgres很好的布尔支持,FTW!):

select

    A, B,

    A = B,
    A IS NOT DISTINCT FROM B, -- "logically" same as above
    coalesce( (A = B) or (A is null and B is null), false ), 
    -- tested Jon's code for ==, semi-work, coalesced to make it true/false only


    A <> B,
    A IS DISTINCT FROM B, -- "logically" same as above
    (A <> B) and (A is not null or B is not null)  
    -- tested Jon's code for !=, bombs out

from(    
    values
    (null, null),
    (null, 'john'),
    (null, 'paul'),
    ('john', null),
    ('john', 'john'),
    ('john', 'paul'),
    ('paul', null),
    ('paul', 'john'),
    ('paul', 'paul')) as x(A,B)
Run Code Online (Sandbox Code Playgroud)

[编辑:发布了与此相关的另一个问题 ]

[编辑:根据Jon对不平等比较的非工作语义的调查发布结果]

select

    A, B,

    A = B,
    A IS NOT DISTINCT FROM B, -- "logically" same as above
    (A = B) or (A is null and B is null), 
    -- tested Jon's code for ==


    A <> B,
    A IS DISTINCT FROM B -- "logically" same as above,
    (A <> B) and (A is not null or B is not null)  
    -- tested Jon's code for !=, bombs out

from(    
    values
    (null, null),
    (null, 'john'),
    (null, 'paul'),
    ('john', null),
    ('john', 'john'),
    ('john', 'paul'),
    ('paul', null),
    ('paul', 'john'),
    ('paul', 'paul')) as x(A,B)


  a   |  b   | ?column? | ?column? | ?column? | ?column? | ?column? | ?column?
------+------+----------+----------+----------+----------+----------+----------
 null | null | null     | t        | t        | null     | f        | f
 null | john | null     | f        | null     | null     | t        | null
 null | paul | null     | f        | null     | null     | t        | null
 john | null | null     | f        | null     | null     | t        | null
 john | john | t        | t        | t        | f        | f        | f
 john | paul | f        | f        | f        | t        | t        | t
 paul | null | null     | f        | null     | null     | t        | null
 paul | john | f        | f        | f        | t        | t        | t
 paul | paul | t        | t        | t        | f        | f        | f
(9 rows)
Run Code Online (Sandbox Code Playgroud)

不平等的非工作语义促使我发布另一个问题 :-)

[编辑:测试乔恩的新答案]

select

    A, B,

    A = B as e,
    A IS NOT DISTINCT FROM B AS e_works, -- "logically" same as above
    (A = B) or (A is null and B is null) AS e_semi_work, -- tested Jon's code for ==, works if we treat null as false


    A <> B as ie,
    A IS DISTINCT FROM B as ie_works, -- "logically" same as above,
    (A <> B) and (A is not null or B is not null) as ie_not_work, -- tested Jon's code for !=, bombs out

    (A <> B) or ((A is null or B is null) and (A is not null or B is not null)) as ie_semi_works, -- this works(well it is, if you treat null as false),

     not ((A = B) or (A is null and B is null)) as ie_not_work2 -- this doesn't work


from(    
    values
    (null, null),
    (null, 'john'),
    (null, 'paul'),
    ('john', null),
    ('john', 'john'),
    ('john', 'paul'),
    ('paul', null),
    ('paul', 'john'),
    ('paul', 'paul')) as x(A,B)
Run Code Online (Sandbox Code Playgroud)

结果:

  a   |  b   | e    | e_works | e_semi_work | ie   | ie_works | ie_not_work | ie_semi_works | ie_not_work2
------+------+------+---------+-------------+------+----------+-------------+---------------+--------------
 null | null | null | t       | t           | null | f        | f           | null          | f
 null | john | null | f       | null        | null | t        | null        | t             | null
 null | paul | null | f       | null        | null | t        | null        | t             | null
 john | null | null | f       | null        | null | t        | null        | t             | null
 john | john | t    | t       | t           | f    | f        | f           | f             | f
 john | paul | f    | f       | f           | t    | t        | t           | t             | t
 paul | null | null | f       | null        | null | t        | null        | t             | null
 paul | john | f    | f       | f           | t    | t        | t           | t             | t
 paul | paul | t    | t       | t           | f    | f        | f           | f             | f
(9 rows)
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 5

再次编辑...合并结果应该有效并使事情变得更简单:

平等:

where COALESCE((A = B) or (A is null and B is null), false)
Run Code Online (Sandbox Code Playgroud)

我同意这不是非常愉快.

编辑:Vilx指出了一个问题A <> B.我认为这会有效:

where (A <> B) or ((A is null or B is null) and
                   (A is not null or B is not null))
Run Code Online (Sandbox Code Playgroud)

这样做可能更简单:

where !(COALESCE((A = B) or (A is null and B is null)), false)
Run Code Online (Sandbox Code Playgroud)