2010-02-14 25 views
7

Tengo una base de datos MySQL que muestra un comportamiento que me gustaría entender mejor. ¿Por qué puedo buscar un valor CHAR insertado en un campo INT? Tengo un campo que es de tipo INT pero parece ser capaz de registrar valores de caracteres, ¿cómo es posible?¿Por qué se pueden insertar caracteres en un campo int de MySQL?

Intenté aislar el problema creando una base de datos con INT y VARCHAR. Inserté "TEST1" en el valor INT pero aún así pude buscar la fila usando el valor de la cadena ID. La advertencia después de insertar la cadena en el valor ID es

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

pero aún así pude buscar ese valor. Me gustaría entender por qué esto es posible.

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) 

La advertencia después de que el SELECT es

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

pero los resultados todavía es correcto.

Esperaría que SELECCIONAR arriba encuentre 0 resultados, pero ese no es el caso, ¿por qué?

RESPUESTA:

Con la ayuda de la respuesta de Asaf abajo y los comentarios de Pekka La respuesta parece obvia ahora.

Durante el INSERT, MySQL no pudo insertar el valor del carácter en un campo INT por lo que lo reemplazó por 0. Lo mismo ocurrió durante SELECT, por lo que estaba haciendo un SELECT en ID = 0 para cualquier valor de carácter I estaba buscando

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

que devuelve el mismo resultado que el de mi selecto inicial, ya que realmente se está ejecutando como

SELECT * FROM test1 WHERE ID = 0; 

en el backend.

En cualquier caso, la mejor práctica parece ser utilizar sql_mode = 'STRICT_ALL_TABLES' en el archivo de configuración de MySQL o en la propia instrucción SQL.

Para habilitar STRICT_ALL_TABLES para todas las consultas SQL en un servidor MySQL que hay que añadir el siguiente bajo el encabezado [mysqld] en el fichero my.cnf que normalmente se encuentra en /etc/my.cnf

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

¿se dio cuenta de MySQL emitió '1 warning' al ejecutar la consulta .. . Tal vez es bueno saber lo que es ...? – Romain

+0

Actualicé la pregunta con los resultados de la advertencia, pero el resultado sigue siendo correcto, que es lo que me pregunto. –

Respuesta

8

puede impedir que los valores sin sentido se inserte en el primer lugar ajustando el modo STRICT_ALL_TABLES que se puede establecer en my.cnf o sobre la marcha:

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

Gracias, lo agregué a la configuración de mi base de datos, ya que parece una buena práctica, pero aún me gustaría saber por qué el SELECT realmente devolvió los resultados correctos. –

+1

+1: genial saber que :) – Sarfraz

+1

@Michael Supongo que la primera conversión (para ID) salió mal, y volvió al valor predeterminado de '0'. –

Cuestiones relacionadas