2009-08-07 5 views
5

Wie Gleichheit von Wert in SQL mit Null zu vergleichen?Wie Gleichheitsvergleich in SQL mit C# ähnlichem Verhalten zu tun?

Für diejenigen, die mit C#, hier sind die Ergebnisse des Vergleichs Nullable-Werte:

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 

Die einfachste Lösung, die ich in SQL gefunden ist, die Nullable-Felder in eine Sentinel-Wert koalesziert (zB ‚scoobydoo‘) dann vergleichen sie

coalesce(A, 'scoobydoo') = coalesce(B, 'scoobydoo') 

Aber das ist klar Flickschusterei, wenn jemand den Sentinel-Wert verwendet, wenn ein NULL sein geschieht und B ‚scoobydoo‘, dann über der Ausdruck wahr ergeben würde

Dieses 210

ist genau mein Ziel für die Logik des Codes auf fragen oben (T-SQL UPDATE-Trigger):

-- detect if the value changes 

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

    -- do something to summary tables here 

end 

Wie Gleichheitsvergleich in SQL mit C# -ähnliche Verhalten zu tun?

[EDIT: Fand die Antwort here]

den Code getestet (Postgres schön boolean Unterstützung, 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) 

[EDIT: Jon Code, seine Antwort auf Gleichheit Arten von halb Getestet -Arbeit (behandeln nur die null als falsch sowieso), aber seine Antwort auf die Ungleichheit Bomben]

den Code getestet (Postgres schön boolean Unterstützung, 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) 

[EDIT: posted andere question einen Bezug zu dieser]

[EDIT: Ergebnisse veröffentlichten basierend auf Jons Anfrage an arbeitsfreien Semantik für Ungleichheit Vergleich]

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) 

die nicht arbeitende Semantik für Ungleichheit mich dazu veranlasst eine weitere question :-)

zu schreiben [EDIT: getestet Jons neue Antwort]

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) 

Ergebnisse:

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) 
+0

s/löschen/gelöscht/in der letzten Probe. Geben Sie explizit Werte für Paul & John an? –

+1

Dup von http://stackoverflow.com/questions/680824/sql-equality-inequality-comparison-with-nullable-values ​​ –

+0

Wenn dies T-SQL ist, ist es definitiv ein Duplikat einer Postgres Frage? Wird die gleiche Antwort funktionieren? –

Antwort

5

bearbeiten wieder ... sollte das Ergebnis koaleszierende arbeiten und macht die Dinge ein wenig einfacher:

Gleichheit:

where COALESCE((A = B) or (A is null and B is null), false) 

Ich stimme es nicht sehr angenehm ist .

EDIT: Vilx wies auf ein Problem mit A <> B.Ich denke, dies obwohl funktioniert:

where (A <> B) or ((A is null or B is null) and 
        (A is not null or B is not null)) 

es einfacher sein kann, dies aber zu tun:

where !(COALESCE((A = B) or (A is null and B is null)), false) 
+0

+1 für die Bereitstellung der unter -the-hood Semantik von IS DISTINCT FROM – Hao

+1

Umm ... verzeihen Sie mir, wenn ich falsch liege, aber würde der zweite nicht scheitern, wenn A wäre NULL und B wäre nicht? –

+0

@Vilx: Um was geht es dir? 'A <> B 'ist wahr, und' (A ist nicht null oder B ist nicht null) 'ist wahr, weil B nicht null ist - also ist das Gesamtergebnis wie gewünscht wahr. –

3

Wenn es Microsoft SQL Server ist, dann sind Sie für die ANSI_NULLS Option suchen. Wenn es ein anderes DBMS ist, müssen Sie die Dokumentation dafür lesen. Einige von ihnen unterstützen dies überhaupt nicht.

Hinzugefügt: Oh, ich habe bemerkt, dass Sie T-SQL erwähnen. Es ist MSSQL dann! :)

+0

Ich mag es ! Ich weiß, es ist nicht der * Standard *, aber verdammt! Vielen Dank. – Kieron

+1

In der Theorie könnte es auch Sybase sein. –

+0

Umm, OK, wusste das nicht. :) –

Verwandte Themen