Le mystère du CONCAT

juillet 19, 2012

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

Comments are closed.