Dziś zauważyłem kolejną ciekawą właściwość MySQL, którą warto odnotować. W przypadku wykonywania złożonych zapytań na „nierównych” tabelach z zastosowaniem złączenia typu LEFT (lub RIGHT) JOIN w wynikach możemy uzyskać rekordy w których część pól jest równa NULL. Jest to oczywista konsekwencja niepełnych danych w jednaj (lub obu) tabelach. Nie zawsze jest to normalny i pożądany stan bazy danych, ale ten temat pomińmy.
Poniżej znajdziecie najprostszą postać zapytanie z LEFT JOIN:
SELECT * FROM t1 LEFT JOIN t2 ON (column1)
Wynik tego zapytania zwrócony przez bazę danych to lista rekordów z pełnymi danymi oraz takimi w których część pól jest równa NULL. Lista obejmuje więc rekordy występujące w obu tabelach oraz w tabeli t1. Właściwością MySQL którą chciałem opisać jest to, że w przypadku takich zapytań dodanie warunku WHERE na kolumnie, która zawiera wartości NULL spowoduje usunięcie również tych rekordów w których dane pole jest równe NULL.
SELECT * FROM t1 LEFT JOIN t2 ON (column1) WHERE t2.column2 NOT LIKE 'clause';
Wykonanie powyższego zapytania uszczupli zwrócone wyniki nie tylko o te spełniające warunek WHERE, ale również usunie wszystkie rekordy w których przypadku wartość t2.column2 jest NULL. Taki sposób działania bazy danych nieco mnie zaskoczył. Osobiście oczekiwałem, że w wyniku działania warunku WHERE otrzymam listę zawierającą również te rekordy które występowały jednostronnie.
Jedynym sensownym rozwiązaniem w takim przypadku jest dodanie dodatkowego warunku zdefiniowanego w następujący sposób:
SELECT * FROM t1 LEFT JOIN t2 ON (column1) WHERE t2.column2 NOT LIKE 'clause' OR t2.column2 IS NULL';
Kolejny raz potwierdza się to, że baza MySQL traktuje NULL dosyć wyjątkowo, więc lepiej uważać jeśli jesteście zmuszeni programować zapytania na tabelach (lub wynikach zapytań), które będą zwracać rekordy zawierające takie wartości.