2013-08-14 11 views
13

Ecco il setup su PostgreSQL 9.2.4:PostgreSQL NON clausola ILIKE non include stringa nulla Valori

CREATE TABLE table (
    id integer NOT NULL, 
    some_text text 
); 

Ora entriamo un record, con una stringa nulla o vuoto per some_text, in modo che quando interroghiamo:

SELECT * FROM table WHERE some_text IS NULL; 

Ricevo indietro la voce. Fin qui tutto bene.

Tuttavia, quando interrogo:

SELECT * FROM table WHERE some_text NOT ILIKE "%anything%'; 

trovo che nulla è stato restituito. Perché? Prevedo che una stringa vuota o vuota non sia "uguale a anything".

risposta

31

In SQL, NULL non è uguale a nulla. Né è ineguale a nulla.

In altre parole, se non ti dico il mio secondo nome e non mi dici il tuo secondo nome, come possiamo sapere se i nostri due secondi nomi hanno lo stesso nome o nomi diversi? Non possiamo saperlo

Questo spesso fa scattare le persone in SQL, perché è una "logica del valore triplo". Un'espressione può essere VERO, FALSO o SCONOSCIUTO. Chi di noi ha familiarità con l'algebra booleana sa che NON TRUE è FALSO e NON FALSO è VERO.

Ma la parte difficile è che NOT UNKNOWN è ancora UNKNOWN.

Quindi la soluzione per voi o è sempre memorizzare una stringa non nulla nella colonna, oppure usare un'espressione per spiegare la logica tri-value:

SELECT * FROM table WHERE some_text NOT ILIKE "%anything%' OR some_text IS NULL; 

Oppure:

SELECT * FROM table WHERE COALESCE(some_text, '') NOT ILIKE '%anything%'; 

PostgreSQL supporta anche una null-safe equality operator:

SELECT * FROM table WHERE some_text IS DISTINCT FROM 'anything'; 

Ma, purtroppo, questo funziona solo per l'uguaglianza, non per LIKE/ILIKE con modelli e caratteri jolly.

+1

Mi piace che sei spiegazione con incognite * *, ma non sono sicuro di come che collega l'SQL. Perché è un 'WHERE null ILIKE '% anything%'' sconosciuto? – applepie

+1

"Giovane, in matematica non capisci le cose, ti ci abitui." - John von Neumann –

+2

oooh il sass. E 'una domanda di follow-up difficile? – applepie

3

Si può usare COALESCE per raggiungere il tuo obiettivo, come

SELECT * FROM table WHERE COALESCE(some_text,'') NOT ILIKE "%anything%';