2 votes

mysql, instructions préparées et conversion automatique des types

J'obtiens des résultats différents en exécutant exactement la même requête à l'aide d'instructions régulières et d'instructions préparées, et je pense qu'il s'agit d'un bogue de conversion de type.

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)

la valeur réelle de vlan es 184

Il semble que la façon dont mysql gère les conversions de type soit différente pour les instructions préparées et les instructions normales. Est-ce que cela a un sens ?

1voto

eggyal Points 60363

Le type de données attendu des paramètres des instructions préparées est déterminé lors de la préparation de l'instruction, et la conversion vers ce type de données a lieu avant l'exécution de l'instruction.

Dans votre exemple, un paramètre entier est attendu ; par conséquent, la chaîne fournie est convertie en un entier (184) avant l'exécution de l'instruction, et la comparaison entre la colonne d'entiers et la colonne d'entiers est effectuée. vlan et le paramètre est accepté pour l'enregistrement correspondant.

L'instruction "regular", en revanche, compare la colonne des nombres entiers avec une chaîne de caractères ; les arguments sont donc comparés en tant que nombres à virgule flottante, et aucun enregistrement n'a de chaîne de caractères correspondante. vlan .

Pour éviter cette situation, il faut s'assurer que le type de données ne peut pas être déterminé lors de la préparation (ou que le type de données déterminé ne perd pas d'informations) - par exemple :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X