Version complète: sur le forum Webmaster Hub : CONCAT_WS
Webmaster Hub > Création et exploitation de Sites Internet > Les langages du Net > SQL
lionel.a
Bonjour,

Selon la documentation MySQL, la fonction CONCAT_WS (= concat "with separator") ne prend pas en compte ni les valeurs nulles, ni les chaînes vides.
Doc mysql.com : concat_ws

Pourtant, chez moi (MySQL: 5.0.45), les valeurs nulles sont sautées, mais pas les chaînes vides.

Ex :
CODE
CONCAT_WS(', ', 'Mot', NULL, 'phrase', '', 'point.')

retourne : Mot, phrase, , point.
au lieu de (selon la doc) : Mot, phrase, point.

Chez vous, qu'est-ce qui est retourné ? Est-ce un problème de documentation, ou de version ? Si ça marche correctement chez vous (= conformément à la doc, c'est-à-dire sans la chaîne vide), merci de me préciser la version de votre mysql.

Merci pour vos réponses,
TheRec
Le comportement que tu décris est le même chez moi. Les chaînes vides ne sont pas ignorées, mais les valeurs NULL le sont. Le problème n'en est pas réellement un, c'est une erreur de traduction du manuel en français apparemment :
CITATION
CONCAT_WS() does not skip empty strings. However, it does skip any NULL values after the separator argument.
Source: MySQL 5.0 Reference Manual :: 11.4 String Functions

Préfère toujours la version originale des manuels si tu le peux car l'adage italien "Traduttore, traditore" (dont le sens est que toute traduction est une trahison) se vérifie bien souvent wink.gif
Kioob
Vu le texte anglais j'ai du mal à croire à une erreur de traduction ; je pencherais plus pour un bug qu'ils ont décidé de "corriger" en modifiant la doc tongue.gif
TheRec
Ou simplement que la documentation originale utilisée pour la traduction a été modifiée entre-temps parce qu'elle était erronée (et que la fonction est prévue pour fonctionner ainsi)... en même temps je ne vois pas en quoi cela change quelque chose le fond de mon propos.
Kioob
Je n'ai pas dit non plus que ça changeait le "fond de ton propos" ; t'énerve pas wink.gif

Je précisait juste cela car ce n'est pas la première fois que MySQL fait le coup. Il y a eu changement de comportement entre les date et datetime il y a peu ; changement "non prévu". Suite aux rapports de bug il a juste été décidé de modifier la doc... sans annoncer pour autant ce changement "majeur" (on se retrouve quand même avec de nombreux scripts dont OpenAds qui ne fonctionnaient plus par exemple).

Bref : oui le problème vient bien d'une "incohérence" dans la version française, c'était bien vu. Mais je ne crois pas une seconde à l'erreur de traduction, mais plutôt à la tentative de "masquage" d'une bourde.
TheRec
CITATION(Kioob @ dimanche 6 avril 2008 à 15:17) *
Je n'ai pas dit non plus que ça changeait le "fond de ton propos" ; t'énerve pas wink.gif

Ne t'inquiète pas, je ne risque pas de m'énerver pour si peu wink.gif Je cherchais à comprendre le but de ton intervention.

Tout dépend du mode de fonctionnement de l'équipe de développement, est-ce que les développeurs documentent leur travail correctement, est-ce que la documentation est rédigée en amont, en aval ou pendant le développement, etc... En plus c'est un développement Open-Source, donc s'il y a vraiment un problème on peut toujours aller au cœur de celui-ci pour comprendre ce qui ne va pas.

Je n'ai pas connaissance du changement des types DATE et DATETIME dont tu parles, aurais-tu plus de détails à ce sujet s'il te plaît ?
Kioob
Je ne retrouve pas le bug en question... on y a été confronté quand on est passé de MySQL 5.0.32 (debian etch) à la version 5.0.45 (backports). Nos scripts n'ont pas été impactés, mais il a fallu qu'on corrige OpenAds.

A priori le problème est le même que pour ce report, mais d'après ce qui est dit cela aurait été finalement corrigé dans la 5.0.51... sic.
Portekoi
Bonjour,

Ajoute un ISnull() pour contourner le problème.

Bye



Porteoi
TheRec
En quoi est-ce que cela résout le problème (pour peu qu'il y en ait un, apparemment c'est le comportement normal de la fonction CONCAT_WS) ?
ISNULL (dans une requête) va retourner 0 ou 1... je ne vois pas où cela serait utile huh.gif
Portekoi
Arf, en Sql Server, Tu peux faire ceci : "isnull(Monchamps, 'valeur si null')

Je ne me souviens plus de l'équivalent sous Mysql... sad.gif
Portekoi
Sous DB2, c'est coalesce mais c'est pas sa pour Mysql... bizarre, je trouve pas l'équivalent...
TheRec
Tu peux certainement utiliser un IF, pas de problème de ce côté ... mais si ISNULL reste inutile, on souhaite détecter une chaîne vide, et ISNULL considère qu'une chaîne vide n'est pas NULL wink.gif Il faudrait utiliser IF et retourner NULL lorsque la comparaison est positive... et ceci pour chaque paramètre de la fonction CONCAT_WS à concaténer.

J'ai tendance à réaliser cela dans le code de l'application, pas sur le serveur de base de donnée, à moins qu'il y ait vraiment besoin de faire une tri ou une autre tâche sur le champ après concaténation. Je mets un exemple à titre indicatif, mais c'est peu représentatif vu que les valeurs sont fixes, ce serait plus représentatif avec des noms de champs wink.gif :

SQL
SELECT CONCAT_WS(', ', IF('Mot' <> '','Mot',NULL), IF(NULL <> '','Mot',NULL), IF('phrase' <> '','phrase',NULL), IF('' <> '','',NULL), IF('point.' <> '','point.',NULL));

À la sortie on se retrouve bien avec :
CITATION
Mot, phrase, point.
Portekoi
Hum pareil avec des CASE (CASE WHEN Isnull(Champ) = 1 or Champ='') THEN ...) ou alors (CASE WHEN Champ+''='') THEN ...)
TheRec
Ouais, en fait ni l'un ni l'autre... NULLIF est le plus approprié après avoir cherché un peu plus dans le manuel ... mais de toute façon toutes ces fonctions font la même chose wink.gif
Mais ça c'est plus court et propre :
SQL
SELECT CONCAT_WS(', ', NULLIF('Mot',''), NULLIF(NULL,''), NULLIF('phrase',''), NULLIF('',''), NULLIF('point.',''));
lionel.a
Whaou, et merci pour toutes ces réponses...

Au passage, j'en profite pour dire que, je crois, la fonction ISNULL s'appelle IFNULL en MySql
IFNULL('valeur_si_pas_Null', 'sinon_valeur')
Mais comme dit TheRec, elles se ressemblent toutes...

Depuis, j'ai aussi pensé à :
CODE
SELECT REPLACE(CONCAT_WS(', ', 'Mot', NULL, 'phrase', '', 'point.'), ', , ', ', ');

Et encore mieux :
CODE
SELECT REPLACE(CONCAT_WS(', ', TRIM('Mot'), TRIM(NULL), TRIM('phrase'), TRIM(''), TRIM('point.')), ', , ', ', ');


Et que je viens de découvrir une fonction qui se rapproche de CONCAT_WS : GROUP_CONCAT(`champ_a_concatener` SEPARATOR ',')
que cette fonction n'a rien à voir avec le "GROUP BY" sauf qu'elle est mal rangée dans la doc MySql (arrêtons de dire du mal... on est bien content de l'avoir cette doc quand même, non ?)
http://dev.mysql.com/doc/refman/5.0/fr/gro...-functions.html

Problème résolu ! Merci
TheRec
Super ! Content d'avoir pu t'aider.

Tes solutions sont partiellement correcte, dans la mesure ou tu peux garantir qu'il n'y aura pas la chaîne ", , " dans les champs qui seront concaténés, sinon elle sera remplacée alors que ce n'était pas un champs de chaîne vide qui aura causé l'apparition de cette chaîne wink.gif

Pour information, ISNULL n'est pas équivalent à IFNULL. La première est une fonction qui retourne 0 ou 1 en évaluant si la valeur testée est NULL ou non. Et IFNULL vérifie si la valeur du premier paramètre est NULL, si c'est le cas la valeur du deuxième paramètre est retournée, sinon c'est la valeur du premier paramètre qui est retournée.

Encore une précision IS NULL n'est pas non plus équivalent à ISNULL, le premier est un opérateur et le second est une fonction wink.gif

Bonne continuation !
Ceci est une version "bas débit" de notre forum. Pour voir la version complète avec plus d'information, la mise en page et les images, veuillez cliquer ici.