2009-12-02 8 views
10

Così, ho chiesto una mattinata a question, che non ho espresso correttamente, quindi ho ricevuto molte risposte sul motivo per cui NULL rispetto a qualsiasi cosa darà NULL/FALSE.disuguaglianza test con colonne che possono essere nulle

La mia vera domanda era, qual è la moda onorata in cui i ragazzi db provano disuguaglianze per due colonne che possono essere entrambe NULL. La mia domanda è l'esatto opposto di questo question.

I requisiti sono come segue, A e B sono due colonne:
a) se A e B sono entrambi NULL, sono uguali, restituire False
b) se A e B sono entrambi non NULL, quindi ritorno a <> B
c) se a o B sono NULL, non sono uguali, restituire TRUE

risposta

8

a seconda del tipo di dati e possibili valori per le colonne:

COALESCE(A, -1) <> COALESCE(B, -1) 

il trucco è trovare un valore (qui ho usato -1) th a piacimento NEVER appaiono nei tuoi dati.

L'altro modo sarebbe:

(A <> B) OR (A IS NOT NULL AND B IS NULL) OR (A IS NULL AND B IS NOT NULL) 

questo può essere un problema a seconda di come il vostro particolare RDBMS gestisce NULL. Secondo lo standard ANSI, questo dovrebbe darti quello che vuoi, ma chi segue comunque gli standard. :)

P.S. - Devo anche sottolineare che l'uso della funzione COALESCE può invalidare l'uso degli indici nel confronto delle colonne. Controlla il piano di query e il rendimento della query per vedere se questo è un problema.

P.P.S. - Ho appena notato che OMG Ponies ha detto che Informix non supporta COALESCE. Credo sia una funzione standard ANSI, ma guarda cosa ho detto sopra sugli standard ...

+0

@Tom: Non che non lo supporti, solo che sembra dipendere dalla versione/edizione. –

+0

E avvolgere la colonna in qualsiasi funzione significa non utilizzare un indice se presente. –

+0

La query di coalesce non funziona se -1 è un valore valido per la colonna. Se lo codifico così, e oggi -1 non è un valore valido, e più tardi diventa un valore valido, questo sarà un bug in cui un campo nullo è uguale a un campo -1. – rouble

0

Se vuoi essere sicuro di come vengono gestiti i NULL, dovrai utilizzare qualsiasi supporto Informix per il controllo Null. Non ho trovato molto, a parte la versione SE non supporta COALESCE, ma supporta DECODE ed eventualmente CASE.

WHERE COALESCE(t.a, 0) != COALESCE(t.b, 0) 
WHERE DECODE(NULL, 0, t.a) != DECODE(NULL, 0, t.b) 
+0

Il coalare a 0 è probabilmente negativo poiché sarebbe uguale a falso. –

+0

@jleedev: il requisito è che 'a' e' b' non debbano essere uguali tra loro. –

+0

Se uno è '0' e l'altro è' NULL', si ottiene '0! = 0', che è falso dove dovrebbe essere vero. –

3

Io personalmente scrivere l'espressione che si avvicinò con, soprattutto se il tavolo è destinato a crescere di grandi dimensioni. Il wrapping delle colonne nelle chiamate alle funzioni fa male alle prestazioni, in quanto il motore non può utilizzare alcun indice presente su quelle colonne. Ovviamente, in un piccolo tavolo, questo potrebbe non essere un problema, ma mi piace ancora farlo in modo esplicito nel caso in cui un tavolo finisca per crescere.

0

Per SQL Server, utilizzare:

WHERE ISNULL(A, '') <> ISNULL(B, '') 
+1

Questo non funziona se '' è un valore valido per la colonna. – rouble

+1

Il DB è informix –

1

si può provare qualcosa di simile in Informix?

CASE 
    WHEN a IS NULL AND B IS NULL THEN false 
    WHEN a IS NULL OR B IS NULL THEN true 
    ELSE a <> B 
END 

da IBM Informix Guide to SQL: Syntax , CASE Expressions

+0

Non so se funzionerebbe in una clausola WHERE –

+0

Sì, CASE-WHEN, COALESCE e NULLIF sono tutti ANSI SQL92 e funzionano in WHERE. – bobince

0

Il problema è che a<>b (o a=b) cede NULL, non 1 o 0 quando uno o entrambi gli operandi sono NULL.Questo non importa per il caso = perché NULL OR 1 è 1 e NULL OR 0 è NULL che si comporta come 0 per la selezione in una clausola WHERE.

Si potrebbe dire:

a<>b OR (a IS NULL)<>(b IS NULL) 

Tuttavia la necessità di farlo in entrambi i casi può essere un segno che si sta abusando NULL e dovrebbe pensare di cambiare lo schema di usare qualche altro valore NOT NULL per indicare questa condizione paragonabile .

Ad esempio, se si dispone di una tabella person con una colonna title, non utilizzare NULL per indicare che non hanno titolo; non è un dato "mancante", è solo che non esiste un titolo. Quindi memorizzalo come una stringa vuota '' che puoi confrontare felicemente con altre stringhe vuote. (Beh, a meno che tu non corra Oracle naturalmente, con il suo problema di stringa vuoto ...)

+0

In realtà, la mia query non funziona. Se solo uno di A o B è NULL, la mia query restituirà FALSE, che è errato. – rouble

+0

Ah ... in realtà non 0 (falso), restituisce NULL a causa del confronto ... ma poi nel caso degli uguali non ha importanza e nei disuguali lo fa. Modifica ... – bobince

+0

@bobince la tua soluzione è molto elegante e corretta, tuttavia dà un errore di sintassi in informix 11.5 – rouble

0

IBM Informix Dynamic Server ha una visione un po 'strana dei booleani per una varietà di motivi storici (noti anche come "cattivi"). Adattando l'idea suggerita da @astander, questa espressione CASE 'funziona', ma sarei il primo a dire 'non ovvio' (vedi - l'ho detto prima di te!). La fase di messa a punto:

create table x(a int, b int); 
insert into x values(null, null); 
insert into x values(null, 1); 
insert into x values(1, null); 
insert into x values(1, 1); 
insert into x values(1, 2); 

L'istruzione SELECT:

SELECT * 
    FROM x 
    WHERE CASE 
      WHEN a IS NULL AND b IS NULL THEN 'f'::BOOLEAN 
      WHEN a IS NULL OR b IS NULL THEN 't'::BOOLEAN 
      WHEN a != b     THEN 't'::BOOLEAN 
      ELSE        'f'::BOOLEAN 
      END 
; 

Il risultato di questa query è:

    1 
     1   
     1   2 

Issues:

  • IDS non riconosce FALSE o VERO o SCONOSCIUTO come parole chiave.
  • IDS non riconosce le espressioni booleane come 'a! = B' (o 'a <> b') come tali.

Sì, mi addolora doverlo affermare.

0

Se

where ((A=B) OR (A IS NULL AND B IS NULL)) 

è per l'uguaglianza, allora perché semplicemente non utilizzare:

where NOT (
    ((A=B) OR (A IS NULL AND B IS NULL)) 
) 

per la disuguaglianza?

Problemi correlati