Bietet Rezepte, Lösungen und ausführliche Beispiele rund um gesundes SQL und zufriedene Datenbanken.
In PHP werden Variablen von den Programmierern gern mit dem Empty String ('') initialisiert. Beispielweise also $sName = ''; . Hierbei wird oft übersehen, dass '' nicht dem NULL-Wert entspricht und dies führt dann schon mal zur Verwirrung.
* IBM DB2 9.1
* MySQL 5.1.30
* ORACLE 10g 10.2 EE
Beginnen wir mit einem kleinen PHP-Skript. Hier wird kurz demonstriert, dass der Empty String ('') nicht dem Wert NULL entspricht. Dies ist wichtig, um die folgenden SQL-Beispiele besser nachvollziehen zu könnnen.
<?php
$sName = '';
if ($sName === '') echo ' Empty String ';
if ($sName === null) echo ' NULL';
?>
=> Empty String
<?php
$sName = null;
if ($sName === '') echo ' Empty String ';
if ($sName === null) echo ' NULL';
?>
=> NULL
Die PHP-Skripte aus Listing 1: zeigen sehr schön, dass sich NULL und Empty String doch deutlicher unterscheiden, als man vielleicht gedacht hat.
Die Datenbank-Tabellen hierfür sehen wie folgt aus:
/**
* MySQL Testtabelle
*/
CREATE TABLE test_null (
id INT NOT NULL,
name VARCHAR(50),
PRIMARY KEY (id)
);
Anschließend werden zwei Datensätze eingefügt. Im Ersten mit den Werten 1 und '', im Zweiten mit 2 und NULL.
/**
* NULL Testdaten
*/
INSERT INTO test_null (id, name) VALUES ( 1, '' );
INSERT INTO test_null (id, name) VALUES ( 2, NULL );
Das Einfügen war kein Problem. Schauen wir mal, ob die Daten vorhanden sind.
/**
* Anzahl Datensätze
*/
SELECT COUNT(*) FROM test_null;
+----------+
| COUNT(*) |
+----------+
| 2 |
+----------+
1 row in set (0.00 sec)
Zwei Datensätze sind vorhanden. Nun sollen diese wieder gelesen werden. Wieviele Datensätze werden mit dieser SQL-Abfrage gefunden?
/**
* SQL-Abfrage mit Empty String
*/
SELECT id, name FROM test_null
WHERE name = '';
+----+------+
| id | name |
+----+------+
| 1 | |
+----+------+
1 row in set (0.00 sec)
Und wieviele Datensätze werden mit dieser "IS NULL" SQL-Abfrage gefunden?
/**
* SQL-Abfrage mit IS NULL
*/
SELECT id, name FROM test_null
WHERE name IS NULL;
+----+------+
| id | name |
+----+------+
| 2 | NULL |
+----+------+
1 row in set (0.00 sec)
Etwas klarer wird das Ganze, wenn wir uns den Inhalt der Spalte name als ASCII Wert ausgeben lassen.
/**
* SQL-Abfrage mit ASCII
*/
SELECT id, ASCII(name) FROM test_null
ORDER BY id;
+----+-------------+
| id | ASCII(name) |
+----+-------------+
| 1 | 0 |
| 2 | NULL |
+----+-------------+
2 rows in set (0.01 sec)
Siehe da, NULL bleibt NULL und bei '' ermittelt die Datenbank den Wert 0. Damit wird nochmal wie in Listing 1: (auf PHP-Ebene) klar gezeigt, dass NULL und '' nicht identisch sind.
Ein zweiter Test soll noch mehr Klarheit zu dem Thema bringen. Wir erstellen eine zweite Tabelle und definieren für die Spalte name den NOT NULL Constraint. Anschließend sollen die Testdaten wieder eingefügt werden.
/**
* MySQL Testtabelle
*/
CREATE TABLE test_not_null (
id INT NOT NULL,
name VARCHAR(50) NOT NULL,
PRIMARY KEY (id)
);
/**
* NULL Testdaten
*/
INSERT INTO test_not_null (id, name) VALUES ( 1, '' );
Query OK, 1 row affected (0.01 sec)
INSERT INTO test_not_null (id, name) VALUES ( 2, NULL );
ERROR 1048 (23000): Column 'name' cannot be null
Listing 9: zeigen den Unterschied. Während der 1. Datensatz diskussionslos eingefügt werden kann, meckert die Datenbank beim zweiten Datensatz mit der Fehlermeldung: Column 'name' cannot be null.
Bei ORACLE 10g R 10.2 werden alle Empty String automatisch in NULL umgewandelt. Was im Falle des Listing 3: und 6: bedeutet, beide Datensätze werden mit NULL eingefügt (auch der Empty String ''). Mit IS NULL werden zwei Datensätze gefunden.
IBM DB2 9.1 wiederum verhält sich identisch zu MySQL. Auch bei IBM wird zwischen dem Empty String und NULL unterschieden.
Bei MySQL und IBM DB2 wird zwischen dem Empty String und NULL unterschieden. Wer da nicht genau weiß, was er tut, kann sich einige Probleme einhandeln. Die MySQL-PDO API bietet einen Parameter $dbh->setAttribute(PDO::ATTR_ORACLE_NULLS, PDO::NULL_EMPTY_STRING) der aber bei meinen Tests mit PHP 5.2.3 und MySQL 5.1.44 keinerlei Wirkung gezeigt hat. Einen anderen (aber meiner Meinung nach nicht schöneren) Weg kann in der Tabellendefinition mit name VARCHAR(50) NOT NULL DEFAULT '' gegangen werden. Dann steht in der Tabelle kein NULL, sondern der Empty String. ORACLE geht die Sache gleich anders an und konvertiert den Empty String zu NULL. Wer irgendwann mal zwischen MySQL, ORACLE oder DB2 wechseln möchte sollte dies bedenken.