2013-08-14 6 views
13

Oto konfiguracja na PostgreSQL 9.2.4:PostgreSQL klauzula ILIKE nie obejmuje łańcuch pusty ceni

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

Teraz wchodzimy jeden rekord z null lub pusty ciąg dla some_text, tak, że gdy zapytanie:

SELECT * FROM table WHERE some_text IS NULL; 

Otrzymuję wpis z powrotem. Jak na razie dobrze.

Jednak, kiedy zapytanie:

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

uważam, że nic nie zostało zwrócone. Dlaczego? Oczekuję, że pusty lub pusty łańcuch będzie "inny niż anything".

Odpowiedz

31

W języku SQL wartość NULL nie jest równa żadnemu. Nic nie jest równe.

Innymi słowy, jeśli nie powiem ci o moim drugim imieniu, a nie powiesz mi o swoim drugim imieniu, to skąd możemy wiedzieć, czy nasze dwa drugie imiona mają tę samą nazwę lub inne imiona? Nie możemy wiedzieć.

Powoduje to częstą edycję osób w SQL, ponieważ jest to "logika trójwartościowa". Wyrażenie może mieć wartość TRUE, FALSE lub UNKNOWN. Ci z nas, którzy znają algebrę boolowską, wiedzą, że NIE PRAWDA jest FAŁSZ, a NIE FAŁSZ jest PRAWDĄ.

Ale najtrudniejsze jest to, że NIEZNANY jest wciąż NIEZNANY.

Więc rozwiązaniem dla ciebie jest albo zawsze przechowywać niezerowym ciąg w kolumnie, albo użyć wyrażenia, aby uwzględnić logiki tri-wartość:

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

czyli

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

PostgreSQL obsługuje również null-safe equality operator:

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

Ale niestety, działa tylko dla równości, nie dla LIKE/ILIKE z wzorami i symbolami wieloznacznymi.

+1

Lubię jesteś wyjaśnienie z niewiadomych * *, ale nie jestem pewien, w jaki sposób łączy się z SQL. Dlaczego "WHERE null ILIKE"% coś% "nieznany? – applepie

+1

"Młody człowieku, w matematyce nie rozumiesz, po prostu się do nich przyzwyczajasz." - John von Neumann –

+2

oooh sass. Czy to trudne pytanie uzupełniające? – applepie

3

Można użyć COALESCE aby osiągnąć swój cel, jak

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