MySQL onderscheid 0 en NULL

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Jelmer -

Jelmer -

09/06/2012 10:09:48
Quote Anchor link
Ik heb een tabel met een kolom `goedgekeurd` tinyint(1) DEFAULT NULL. Nu wil ik uit die tabel alle regels hebben waarbij gekeurd niet 0 (afgekeurd) is (dus alleen 1: goedgekeurd of NULL: nog niet gekeurd) Lijkt simpel:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
SELECT * FROM tabel WHERE gekeurd != 0


Maar nu geeft hij ook de rijen waar gekeurd NULL is niet terug. Hoe krijg ik MySQL zo ver dat hij NULL en 0 niet als gelijk behandeld in dit geval? Ik begin m'n verbinding al met:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
SET SESSION sql_mode = 'TRADITIONAL,ONLY_FULL_GROUP_BY,NO_AUTO_VALUE_ON_ZERO'


Wat overigens wel werkt, maar.. toch.. dit is lelijk:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
SELECT * FROM tabel WHERE gekeurd = 1 OR gekeurd IS NULL
 
PHP hulp

PHP hulp

18/12/2024 08:11:42
 
Erwin H

Erwin H

09/06/2012 10:17:59
Quote Anchor link
Op NULL moet je altijd testen door middel van IS NULL of IS NOT NULL. NULL is namelijk niets en kan je niet vergelijken met een andere waarde. Elke vergelijking levert dan false op. Dus NULL = 0 is false en NULL <> 0 is ook false.

Je laatste statement is dus de enige juiste, ook al vind je het lelijk.
 
Ger van Steenderen
Tutorial mod

Ger van Steenderen

09/06/2012 13:02:40
Quote Anchor link
Helemaal correct. Overigens hoef je een nullable kolom geen default waarde NULL mee te geven. Ik persoonlijk geef er de voorkeur aan dan wel een een specifieke waarde op te geven.
 
Bartje Jansen

Bartje Jansen

09/06/2012 13:31:27
Quote Anchor link
Ger van Steenderen op 09/06/2012 13:02:40:
Helemaal correct. Overigens hoef je een nullable kolom geen default waarde NULL mee te geven.

Huh? NULL is het ontbreken van een bekende waarde, er valt niks te zeggen over deze onbekende waarde. Dus hoe wil je dan de default waarde NULL opgeven wanneer het geen waarde is?

Wanneer je niks invult en geen default waarde hebt gedefinieerd voor een kolom, blijft deze automatisch NULL.

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
CREATE TABLE test(id INT, getal INT);

INSERT INTO test(id) VALUES(1);
INSERT INTO test(id,getal) VALUES(2, NULL); -- NULL mag niet tussen quotes staan!

SELECT id, getal FROM test WHERE id = 1;

SELECT id, getal FROM test WHERE getal IS NULL;


MySQL doet rare dingen met NULL's, in elk geval met DATE en DATETIME. Vertrouw daar niet op, maar dat kan met MySQL toch al niet...

Ps. Volgens mij bedoel je het wel goed, leg je het alleen wat ongelukkig uit.

Toevoeging op 09/06/2012 13:41:50:

Jelmer rrrr op 09/06/2012 10:09:48:
Wat overigens wel werkt, maar.. toch.. dit is lelijk:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
SELECT * FROM tabel WHERE gekeurd = 1 OR gekeurd IS NULL

Wat je (in theorie) zou kunnen doen, is COALESCE() gebruiken:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
SELECT * FROM tabel WHERE COALESCE(gekeurd,1) = 1

COALESCE() vervangt een NULL (in dit geval) door een 1. En dan heb je weer een match.

Máár.... hierdoor kan de database géén gebruik meer maken van een index op de kolom "gekeurd". Wanneer er weinig records in deze tabel staan, is dat geen probleem, in andere gevallen kan dit een performance probleem worden. Dus mocht je al een index op deze kolom hebben staan, is dit waarschijnlijk geen bruikbare oplossing.

Ps. Een kolom "status" van het type INT, SMALLINT of TINYINT die verwijst naar een andere tabel (met foreign key) met alle mogelijke statussen, lijkt mij fraaier. Een boolean (tinyint in jouw geval) duidt vaak op een sub-optimaal datamodel. In dat geval heb je het probleem van COALESCE en een index ook niet meer.
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.