Documentation :

Un des reproches couramment fait à MySQL est son manque de respect des standards du Langage SQL. Et en effet il est vrai qu'il peut sembler laxiste. Cependant, il est possible de modifier son comportement pour respecter de manière plus stricte les standards. Ces options ne sont pas activées par défaut pour ne pas bloquer le fonctionnement des applications existantes.

Un exemple en mode classique :

mysql> CREATE TABLE `essai`.`Test` (
-> `Ref` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
-> `Nom` VARCHAR( 10 ) NOT NULL ,
-> `Dat` DATE NOT NULL ,
-> PRIMARY KEY ( `Ref` )
-> ) ENGINE = innodb CHARACTER SET utf8 COMMENT = 'Test SQL Mode';
Query OK, 0 rows affected (0.00 sec)
mysql> SET sql_mode='';
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO Test SET Nom="Hello";
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> INSERT INTO Test SET Nom='Hello';
Query OK, 1 row affected, 1 warning (0.01 sec)
mysql> INSERT INTO Test SET Nom='empty date', Dat='';
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> INSERT INTO Test SET Nom='2008-04-31', Dat='2008-04-31';
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> INSERT INTO Test SET Nom='2008-05-01', Dat='2008-05-01';
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO Test SET Nom='Very long string', Dat=NOW();
Query OK, 1 row affected, 2 warnings (0.00 sec)
mysql> SELECT * From Test;
+-----+------------+------------+
| Ref | Nom | Dat |
+-----+------------+------------+
| 1 | Hello | 0000-00-00 |
| 2 | Hello | 0000-00-00 |
| 3 | empty date | 0000-00-00 |
| 4 | 2008-04-31 | 0000-00-00 |
| 5 | 2008-05-01 | 2008-05-01 |
| 6 | Very long | 2008-04-27 |
+-----+------------+------------+

On voit ici que toutes les requêtes sont acceptées, et que les résultats ne correspondent pas forcément au but rechercher par le développeur.

Maintenant, la même chose en mode strict :

mysql> TRUNCATE Test;
Query OK, 6 rows affected (0.01 sec)
mysql> SET sql_mode='STRICT_ALL_TABLES,ANSI_QUOTES,NO_AUTO_VALUE_ON_ZERO,NO_ZERO_DATE,NO_ZERO_IN_DATE';
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO Test SET Nom="Hello";
ERROR 1054 (42S22): Unknown column 'Hello' in 'field list'
mysql> INSERT INTO Test SET Nom='Hello';
ERROR 1364 (HY000): Field 'Dat' doesn't have a default value
mysql> INSERT INTO Test SET Nom='empty date', Dat='';
ERROR 1292 (22007): Incorrect date value: '' for column 'Dat' at row 1
mysql> INSERT INTO Test SET Nom='2008-04-31', Dat='2008-04-31';
ERROR 1292 (22007): Incorrect date value: '2008-04-31' for column 'Dat' at row 1
mysql> INSERT INTO Test SET Nom='2008-05-01', Dat='2008-05-01';
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO Test SET Nom='Very long string', Dat=NOW();
ERROR 1406 (22001): Data too long for column 'Nom' at row 1
mysql> SELECT * From Test;
+-----+------------+------------+
| Ref | Nom | Dat |
+-----+------------+------------+
| 1 | 2008-05-01 | 2008-05-01 |
+-----+------------+------------+
1 row in set (0.00 sec)

Lorsque ce mode est activé, seule les requêtes totalement valides sont exécutées. Il est souvent préférable d'avoir un message d'erreur que d'accepter l'enregistrement de données corrompues.

De plus, il semblerait que certaines distributions de MySQL active désormais le mode strict par défaut (notament sous Windows). Cela peut provoquer de très mauvaises surprises si vos développements ne sont pas impeccables.

Conclusion

Si vous développez avec MySQL je vous recommande donc d'activer le mode strict, cela vous permettra de vérifier la qualité de votre code et d'éviter de nombreux rapport de bugs de vos utilisateurs. Pour cela, dans le fichier de configuration (/etc/my.cnf), ajouter dans la section du serveur ([mysqld]) :

sql-mode=STRICT_ALL_TABLES

Voir, encore plus exigeant :

sql-mode=STRICT_ALL_TABLES,ANSI_QUOTES,NO_AUTO_VALUE_ON_ZERO,NO_ZERO_DATE,NO_ZERO_IN_DATE

N'oubliez pas de consulter la documentation pour bien comprendre l'impact de chacune des options disponibles. Plus vous serez exigeant, plus votre code a de chance d'être portable.

Au travail !