Le mystère du CONCAT
Un comportement bizarre m’a été remontée par un collègue.
J’ai une table qui contient des IDs (pas la clé primaire):
SELECT DISTINCT ID FROM Connection WHERE…\G *************************** 1. row *************************** ID: 12345678
J’utilise la fonction CONCAT pour concaténer une chaîne de caractères et les IDs de la table:
SELECT DISTINCT ID, CONCAT(‘Daz_’,ID) AS Concat FROM Connection WHERE…\G *************************** 1. row *************************** ID: 12345678 Concat: Daz_1234
Pour une raison qui m’échappe, l’ID concaténé est tronqué ! Bug ou feature ???
Si je rajoute une autre chaîne de caractères à concaténer, le résultat est encore plus surprenant…
SELECT DISTINCT ID, CONCAT(‘Daz_’,ID,’abcd’) AS Concat FROM Connection WHERE…\G *************************** 1. row *************************** ID: 12345678 Concat: Daz_12345678
L’ajout de 4 caractères me permet d’avoir la suite de mon nombre ie les 4 chiffres suivants (sic).
Si j’agrandis la chaîne, je peux enfin voir, dans le résultat de la concaténation, les premiers caractères de ma chaîne.
SELECT DISTINCT ID, CONCAT(‘Daz_’,ID,’abcdef‘) AS Concat FROM Connection WHERE…\G *************************** 1. row *************************** ID: 12345678 Concat: Daz_12345678ab
Bref c’est du grand n’importe quoi !!! A ce stade, je suis persuadé que ce n’est pas une feature 🙂
Alors on fait quoi avec ça ?
Avec ces 2 derniers exemples, un fix quick & dirty permet, dans le contexte d’utilisation de mon collègue, de contourner ce problème.
Concaténer avec des espaces, 4 dans son cas :
SELECT DISTINCT ID, CONCAT(‘Daz_’,ID,‘ ‘) AS Concat FROM Connection WHERE…\G *************************** 1. row *************************** ID: 12345678 Concat: Daz_12345678
Mais si mon ID contient plus de 8 chiffres, ça ne fonctionne pas (bah oui quick & dirty j’ai dis) !
Avant d’aller plus loin, il est rassurant de constater que sans DISTINCT, le comportement est plus proche du résultat attendu :
SELECT ID, CONCAT(‘Daz_’,ID) AS Concat FROM Connection WHERE…\G *************************** 1. row *************************** ID: 12345678 Concat: Daz_12345678
J’ai également testé avec un GROUP BY sur ID et… le comportement est le même. Le problème semble venir de la table temporaire nécessaire pour dédoublonner.
La solution est dans le CAST
Le contournement est de fixer la taille de la sortie concaténée en utilisant la fonction CAST:
SELECT DISTINCT ID, CAST(CONCAT(‘Daz_’,ID) AS CHAR(255) ) AS Concat FROM Connection WHERE…\G *************************** 1. row *************************** ID: 12345678 Concat: Daz_12345678
CQFD
N.B. Server version: 5.5.12-rel20.3-log Percona Server with XtraDB (GPL), Release rel20.3, Revision 118
P.S. Merci à Nico pour m’avoir remonté ce comportement bizarre
P.S2.: ce comportement est à rapprocher du Bug #39543
Architecte Solution Cloud chez Oracle
MySQL Geek, Architecte, DBA, Consultant, Formateur, Auteur, Blogueur et Conférencier.
—–
Blog: www.dasini.net/blog/en/
Twitter: https://twitter.com/freshdaz
SlideShare: www.slideshare.net/freshdaz
Youtube: https://www.youtube.com/channel/UC12TulyJsJZHoCmby3Nm3WQ
—–