2010-02-14 21 views
7

Mam bazę danych MySQL, która wyświetla zachowanie, które chciałbym lepiej zrozumieć. Dlaczego mogę wyszukać wartość CHAR wstawioną do pola INT? Mam pole, które jest typu INT, ale wydaje się być w stanie rejestrować wartości znaków, jak to możliwe?Dlaczego można wstawiać znaki do pola int MySQL?

Próbowałem wyizolować problem, tworząc bazę danych z INT i VARCHAR. Wstawiłem "TEST1" do wartości INT, ale wciąż byłem w stanie wyszukać wiersz za pomocą wartości ciągu ID. Ostrzeżenie po wstawieniu ciągu znaków do wartości identyfikatora to

| Warning | 1366 | Incorrect integer value: 'TEST1' for column 'ID' at row 1 | 
, ale wciąż byłem w stanie wyszukać tę wartość. Chciałbym zrozumieć, dlaczego jest to możliwe.

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) 

Ostrzeżenie po SELECT

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

ale wyniki są nadal poprawne.

Spodziewam się, że powyższy SELECT znajdzie 0 wyników, ale tak nie jest, dlaczego?

ODPOWIEDŹ:

Dzięki za odpowiedź Asafa poniżej i komentarze Pekka za odpowiedź wydaje się oczywista teraz.

Podczas INSERT, MySQL nie wstawił wartości znaku do pola INT, więc zastąpił ją 0. To samo stało się podczas SELECT, więc w efekcie robiłem SELECT na ID = 0 dla dowolnej wartości znaku I szukał.

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

która zwraca ten sam wynik jak mój początkowy wybierz ponieważ to naprawdę działa jak

SELECT * FROM test1 WHERE ID = 0; 

w backend.

W każdym przypadku najlepszą praktyką wydaje się używanie sql_mode = 'STRICT_ALL_TABLES' w pliku konfiguracyjnym MySQL lub samej instrukcji SQL.

Aby włączyć STRICT_ALL_TABLES dla wszystkich zapytań SQL na serwerze MySQL trzeba dodać następujące pod [mysqld] nagłówka w pliku my.cnf który zazwyczaj znajduje się w /etc/my.cnf

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

Zauważyłeś MySQL wydane '1 warning' podczas wykonywania zapytanie .. Może dobrze wiedzieć, co to jest ...? – Romain

+0

Zaktualizowałem pytanie z wynikami ostrzeżenia, ale wynik jest nadal poprawny, o to właśnie się zastanawiam. –

Odpowiedz

8

można zapobiec wartości nonsensowne przed włożony w pierwszej kolejności poprzez ustawienie trybu STRICT_ALL_TABLES które można ustawić w my.cnf lub w locie:

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

Dziękuję, dodałem to do mojej konfiguracji bazy danych, ponieważ wydaje się, że jest to najlepsza praktyka, ale nadal chciałbym wiedzieć, dlaczego SELECT rzeczywiście zwrócił poprawne wyniki. –

+1

+1: świetnie to wiedzieć :) – Sarfraz

+1

@Michael Zakładam, że pierwsza konwersja (dla ID) poszło nie tak i przywrócono domyślną wartość '0'. –

Powiązane problemy