mysql, подготовленные операторы и автоматическое преобразование типов - PullRequest
2 голосов
/ 04 марта 2011

Я получаю разные результаты, выполняя один и тот же запрос, используя регулярные операторы и подготовленные операторы, и я думаю, что это ошибка преобразования типов.

mysql> show columns from server where field = "vlan";
+-------------+--------+------+-----+---------+-------+
| Field       | Type   | Null | Key | Default | Extra |
+-------------+--------+------+-----+---------+-------+
| vlan        | int(5) | YES  | MUL | NULL    |       |
+-------------+--------+------+-----+---------+-------+

mysql> select hostname from server where `vlan` = '184.182' limit 1;
Empty set (0.00 sec)

mysql> prepare stupid from "select hostname from server where `vlan` = ? limit 1";
Query OK, 0 rows affected (0.00 sec)
Statement prepared

mysql> set @vlan = '184.182';
Query OK, 0 rows affected (0.00 sec)

mysql> execute stupid using @vlan;
+-------------------+
| hostname          |
+-------------------+
| web20.servers.com |
+-------------------+
1 row in set (0.00 sec)

реальное значение vlan равно 184

похоже, что mysql обрабатывает преобразования типов по-разному для подготовленных операторов и регулярных операторов? Имеет ли это смысл? как мне это исправить?

1 Ответ

1 голос
/ 08 мая 2012

Ожидаемый тип данных подготовленных параметров оператора определяется при подготовке оператора, и преобразование типа в этот тип данных происходит до выполнения оператора.

В вашем примере ожидается целочисленный параметр; поэтому предоставленная строка преобразуется в целое число (184) перед выполнением оператора, и сравнение между целочисленным столбцом vlan и параметром является успешным для соответствующей записи.

«Обычный» оператор, напротив, сравнивает целочисленный столбец со строкой; поэтому аргументы сравниваются как числа с плавающей запятой, и ни одна запись не имеет соответствия vlan.

Чтобы избежать этой ситуации, убедитесь, что тип данных не может быть определен при подготовке (или что определенный тип данных не теряет никакой информации) - например:

prepare not_so_stupid from
  "select hostname from server where `vlan` = CAST(? AS CHAR) limit 1"
;
...