Voici un comportement particulier, mais logique, que vous n’avez peut-être pas remarqué si vous n’êtes jamais tombé sur ce cas : la comparaison de valeurs avec MySQL, quand un champ est NULL.
Nous allons voir un exemple simple pour illustrer ce cas.
Voici une table User :
idUser | nom | prenom |
---|---|---|
1 | Dupont | Marc |
2 | Dupont | Jean |
3 | Martin | Charles |
4 | NULL | The Truth |
5 | Luffy |
On a 2 utilisateurs sans nom, un dont la valeur est à NULL, et l’autre qui est une chaîne de caractère vide.
Si on veut extraire de cette table tous les utilisateurs qui ne sont pas des Dupont, on pourrait écrire ça :
try {
$db = new PDO('mysql:dbname=test;host=localhost', 'userdb', 'monpass');
} catch (PDOException $e) {
die('Connexion échouée : ' . $e->getMessage());
}
$param = array(
'nom' => 'Dupont'
);
$stmt = $db->prepare('SELECT * FROM User WHERE nom != :nom');
$stmt->execute($param);
$result = $stmt->fetchAll(PDO::FETCH_CLASS);
var_dump($result);
Dans notre résultat on peut espérer avoir : Martin Charles, The Truth et Luffy, seulement en regardant le dump on s’aperçoit qu’il manque notre utilisateur The Truth.
En effet MySQL ne considère pas NULL comme étant comparable à une quelconque chaîne de caractère puisque ça n’en est pas une, il ne renvoie donc pas cet enregistrement.
De la même façon ces requêtes ne reverront pas l’utilisateur The Truth :
$stmt = $db->prepare('SELECT * FROM User WHERE nom NOT LIKE :nom');
$stmt = $db->prepare('SELECT * FROM User WHERE nom = ""');
Il faut donc préciser dans la requête que l’on souhaite également avoir la valeur NULL dans nos résultats.
Ces 2 requêtes nous renverrons bien les 3 derniers enregistrements de notre table User.
$stmt = $db->prepare('SELECT * FROM User WHERE nom != :nom OR nom IS NULL');
$stmt = $db->prepare('SELECT * FROM User WHERE nom NOT LIKE :nom OR nom IS NULL');