2010-02-14 4 views
7

J'ai une base de données MySQL qui présente un comportement que j'aimerais mieux comprendre. Pourquoi puis-je rechercher une valeur CHAR insérée dans un champ INT? J'ai un champ de type INT mais il semble être capable d'enregistrer des valeurs de caractères, comment est-ce possible?Pourquoi pouvez-vous insérer des caractères dans un champ int MySQL?

J'ai essayé d'isoler le problème en créant une base de données avec un INT et VARCHAR. J'ai inséré "TEST1" dans la valeur INT mais j'étais toujours capable de rechercher la ligne en utilisant la valeur de la chaîne ID. L'avertissement après l'insertion de la chaîne dans la valeur ID est

| Warning | 1366 | Incorrect integer value: 'TEST1' for column 'ID' at row 1 | 

mais j'ai quand même réussi à rechercher cette valeur. Je voudrais comprendre pourquoi c'est possible.

mysql> CREATE TABLE test1(ID int, DATA varchar(255)); 
Query OK, 0 rows affected (0.18 sec) 

mysql> INSERT INTO test1(ID,DATA) VALUES('TEST1', 'TEST1'); 
Query OK, 1 row affected, 1 warning (0.00 sec) 

mysql> SELECT * FROM test1 WHERE ID = 'TEST1'; 
+------+-------+ 
| ID | DATA | 
+------+-------+ 
| 0 | TEST1 | 
+------+-------+ 
1 row in set, 1 warning (0.00 sec) 

L'avertissement après SELECT est

| Warning | 1366 | Incorrect integer value: 'TEST1' for column 'ID' at row 1 | 

mais les résultats sont toujours correctes.

Je m'attendais à voir le SELECT ci-dessus pour trouver 0 résultats, mais ce n'est pas le cas, pourquoi?

RÉPONSE:

Avec l'aide de la réponse Asaph ci-dessous et les commentaires de Pekka la réponse semble évidente maintenant. Pendant l'INSERT, MySQL n'a pas réussi à insérer la valeur du caractère dans un champ INT, donc il l'a remplacé par 0. La même chose s'est produite pendant le SELECT, donc je faisais un SELECT sur ID = 0 pour toute valeur de caractère. cherchait.

mysql> SELECT * FROM test1 WHERE ID = 'SOMETHING_OTHER_THAN_TEST1'; 
+------+-------+ 
| ID | DATA | 
+------+-------+ 
| 0 | TEST1 | 
+------+-------+ 
1 row in set, 1 warning (0.00 sec) 

qui renvoie le même résultat que la première sélection de mon car il est vraiment en cours d'exécution comme

SELECT * FROM test1 WHERE ID = 0; 

dans le back-end.

Dans tous les cas, la meilleure pratique semble être d'utiliser sql_mode = 'STRICT_ALL_TABLES' dans le fichier de configuration MySQL ou dans l'instruction SQL elle-même.

Pour activer STRICT_ALL_TABLES pour toutes les requêtes SQL sur un serveur MySQL vous devez ajouter ce qui suit dans l'en-tête [mysqld] dans votre fichier my.cnf qui est habituellement situé dans /etc/my.cnf

[mysqld] 
... 
... 
... 
sql-mode=STRICT_ALL_TABLES 
+1

Avez-vous remarqué MySQL émis '1 warning' lors de l'exécution de votre requête .. Peut-être que c'est bon de savoir ce que c'est ...? – Romain

+0

J'ai mis à jour la question avec les résultats de l'avertissement, mais le résultat est toujours correct, c'est ce que je me demande. –

Répondre

8

vous pouvez empêcher les valeurs non-sens d'être inséré en premier lieu en réglant le mode STRICT_ALL_TABLES qui peut être mis en my.cnf ou à la volée:

mysql> SET sql_mode = 'STRICT_ALL_TABLES'; 
Query OK, 0 rows affected (0.00 sec) 

mysql> CREATE TABLE test1(ID int, DATA varchar(255)); 
Query OK, 0 rows affected (0.42 sec) 

mysql> INSERT INTO test1(ID,DATA) VALUES('TEST1', 'TEST1'); 
ERROR 1264 (22003): Out of range value adjusted for column 'ID' at row 1 
mysql> SELECT * FROM test1 WHERE ID = 'TEST1'; 
Empty set (0.00 sec) 

mysql> SELECT * FROM test1; 
Empty set (0.00 sec) 
+1

Merci, j'ai ajouté cela à ma configuration de base de données car cela semble être une bonne pratique, mais j'aimerais quand même savoir pourquoi le SELECT a effectivement renvoyé les bons résultats. –

+1

+1: c'est bien de savoir que :) – Sarfraz

+1

@Michael Je suppose que la première conversion (pour ID) a mal tourné, et elle est revenue à la valeur par défaut de '0'. –

Questions connexes