IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Requêtes MySQL Discussion :

Comment supprimer un ID faisant partie d'une liste dans un champ string ?


Sujet :

Requêtes MySQL

  1. #1
    Membre éclairé
    Avatar de clavier12AZQSWX
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Avril 2009
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Somme (Picardie)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : Avril 2009
    Messages : 1 418
    Points : 873
    Points
    873
    Par défaut Comment supprimer un ID faisant partie d'une liste dans un champ string ?
    bonjour,

    j'ai un champs string qui se comportent comme une liste de IDS, par exemple

    id,nom,liste
    1 toto 1,2,52
    2 julie 1,5,3
    3 dupont 15,5,6
    4 sarah 5
    6 julien 5,4
    si je veux retirer l'élément 5 dans les champs 'liste', c-a-d supprimer '5' de la chaine liste , comment faire en une étape ?

    je dis bien en une étape, car je sais que je peux le faire en 4 étapes (des sql update avec replace). j'ai 4 étapes car je ne peux pas juste faire un replace du 5 sinon je vais bousiller les 52,15 et je dois gérer le positionnement de la virgule !
    Mysql n'a-t-il pas une fonction intégrée pour gérer les champs de type liste ?

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Responsable Données
    Inscrit en
    Janvier 2009
    Messages
    5 240
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Responsable Données

    Informations forums :
    Inscription : Janvier 2009
    Messages : 5 240
    Points : 12 872
    Points
    12 872
    Par défaut
    Bonjour,
    tu peux utiliser nu CASE dans la "partie" affectation" de la colonne:
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    update MaTable
    set MaColonne = case 
    when Macolonne = '5' then null
    when MaColonne like '5,%' then right(MaColonne, length(MaColonne) - 2
    when MaColonne like '%,5' then Left(MaColonne, length(MaColonne) - 2
    else MaColonne = replace(MaColonne, ',5,','')

    Tu peux ajouter nu filtre pour ne prendre que les lignes concernées, mais dans tous les cas aucun index ne sera éligible ici.

    Tatayo.

  3. #3
    Membre éclairé
    Avatar de clavier12AZQSWX
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Avril 2009
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Somme (Picardie)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : Avril 2009
    Messages : 1 418
    Points : 873
    Points
    873
    Par défaut
    oui , une requête avec 4 cases est moins couteux en serveur que 4 update..
    ça reste une écriture sql "encombrante"
    n'y-a-t-il pas dans mysql (comme en php), des fonctions spécifiques aux "array" ?
    si c'était le cas j'aurai pu utiliser "WHERE 5 IN macolonne" pour déjà mieux cibler

    dommage que ya pas pas
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    UPDATE matable set macolonne=enlever(5) where  5 IN macolonne "

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Responsable Données
    Inscrit en
    Janvier 2009
    Messages
    5 240
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Responsable Données

    Informations forums :
    Inscription : Janvier 2009
    Messages : 5 240
    Points : 12 872
    Points
    12 872
    Par défaut
    Mysql propose la fonction REGEXP_REPLACE() qui doit faire le job.

    Il ne te reste plus qu'à trouver l'expression régulière qui va bien.

    Tatayo.

  5. #5
    Membre éclairé
    Avatar de clavier12AZQSWX
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Avril 2009
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Somme (Picardie)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : Avril 2009
    Messages : 1 418
    Points : 873
    Points
    873
    Par défaut
    je suis pas très à l'aise avec le RegX , je viens de voir qu'il y a la fonction TRIM, je vais peut-être arriver à réduire les cas...
    https://www.w3resource.com/mysql/str...m-function.php

  6. #6
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 099
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 9 099
    Points : 28 390
    Points
    28 390
    Par défaut
    Cela démontre une fois de plus qu'avec un modèle de données mal construit on rencontre rapidement des problèmes qui ne peuvent être résolus de manière simple.
    On ne gère pas une liste dans une colonne ! On crée une table fille pour y placer la liste.

    Au lieu de la table Table1(#Id_T1, Attributs_T1, ListeDeValeurs), il faudrait Table1(#Id_T1, Attributs_T1) et Table2(*Id_T1, Valeur), avec une seule valeur de la liste dans chaque ligne.
    Et là, plus de contorsion pour trouver une valeur dans la liste, la supprimer, la remplacer...

  7. #7
    Expert éminent
    Avatar de Séb.
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    5 198
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 198
    Points : 8 421
    Points
    8 421
    Billets dans le blog
    17
    Par défaut
    si je veux retirer l'élément 5 dans les champs 'liste', c-a-d supprimer '5' de la chaine liste , comment faire en une étape ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    UPDATE ta_table
    SET ta_liste = TRIM(BOTH ',' FROM REPLACE(',' || ta_liste || ',', ',5,', ','));
    1. On ajoute le délimiteur avant/après la valeur à supprimer => Pour être sûr de bien supprimer la valeur souhaitée uniquement
    2. On ajoute le délimiteur en début et fin de liste => Pour gérer les recherches en début/fin de liste
    3. On remplace la valeur à supprimer encadrée du délimiteur par le délimiteur seul => Pour que la liste reste correctement construite
    4. On supprime les délimiteurs encadrants ajoutés pour l'exercice => On remet à neuf

    C'est moche mais ça marche.

    Passe plutôt par une 2nde table ou du JSON.

  8. #8
    Membre éclairé
    Avatar de clavier12AZQSWX
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Avril 2009
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Somme (Picardie)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : Avril 2009
    Messages : 1 418
    Points : 873
    Points
    873
    Par défaut
    Citation Envoyé par al1_24 Voir le message
    Cela démontre une fois de plus qu'avec un modèle de données mal construit on rencontre rapidement des problèmes qui ne peuvent être résolus de manière simple.
    On ne gère pas une liste dans une colonne ! On crée une table fille pour y placer la liste.

    Au lieu de la table Table1(#Id_T1, Attributs_T1, ListeDeValeurs), il faudrait Table1(#Id_T1, Attributs_T1) et Table2(*Id_T1, Valeur), avec une seule valeur de la liste dans chaque ligne.
    Et là, plus de contorsion pour trouver une valeur dans la liste, la supprimer, la remplacer...
    je vous rejoins sur ce point à 100%

    Quand j'ai appris le SQL ya des décénies, on nous apprenez l'existence du type SET de mysql ... Or dans aucun cours, on nous a appris à choisir/refuser un type SET et préférer/éviter une table fille....

  9. #9
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 302
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 302
    Points : 39 647
    Points
    39 647
    Billets dans le blog
    9
    Par défaut
    Dans l'apprentissage de la modélisation des bases de données, on aborde notamment les formes normales.
    Or, la première d'entre-elles stipule justement que chaque intersection ligne/colonne ne doit contenir qu'une et une seule valeur !
    (on trouve souvent le terme "valeur atomique" à ce sujet, mais c'est un abus de langage)

    La remarque de AL1__24 est donc incontournable.

  10. #10
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 420
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 420
    Points : 19 228
    Points
    19 228
    Par défaut
    Salut à tous.

    Citation Envoyé par clavier12AZQSWX
    j'ai un champs string qui se comportent comme une liste de IDS, par exemple
    On ne dit pas champs, mais colonne. Apprenez à utiliser le vocabulaire adéquate.

    Je n'aime pas trop les sigles surtout quand leur signification peuvent être multiples.
    Qu'est-ce que vous entendez par IDS ? (peut être Integrated Data Store comme le nom du SGBD sous BULL).

    Citation Envoyé par clavier12AZQSWX
    si je veux retirer l'élément 5 dans les champs 'liste', c-a-d supprimer '5' de la chaine liste , comment faire en une étape ?
    L'astuce de Seb. fonctionne parfaitement, je l'ai testé, sauf qu'elle n'a pas la bonne syntaxe sous MySql :
    Code mysql : Sélectionner tout - Visualiser dans une fenêtre à part
    UPDATE `test` SET liste =trim(both ',' from replace(concat(',',`liste`,','),',5,',','));

    Citation Envoyé par clavier12AZQSWX
    Mysql n'a-t-il pas une fonction intégrée pour gérer les champs de type liste ?
    La colonne "liste" n'a pas lieu d'être car vous faites un mauvais usage des SET.
    Un SET est une colonne qui va admettre une liste de valeurs, c'est-à-dire à choix multiple.
    Un ENUM fonctionne presque pareil que le SET sauf qu'il admet qu'une seule valeur possible.
    Voir la documentation MySql :
    --> Type Set.
    --> [https://dev.mysql.com/doc/refman/8.0/en/enum.html]TypeEnum[/url].

    Il n'existe aucune fonction pour faire des substitutions car le but de ce stockage est de donner la liste des valeurs admissible à l'insertion.
    D'autre part dans le type set comme dans le type enum, ce qui est stocké est la position de la valeur dans la liste.
    Par exemple, si mon set est composé de ('a', 'b', 'c') et que je stocke 'c', la valeur stocké est 3.

    Si vous avez besoin de connaitre si l'une de ces valeurs a été renseignées, vous devez utiliser la fonction "Find_In_Set()".

    La bonne façon de gérer votre colonne "liste" puisqu'il ne s'agit pas d'une colonne à choix multiple comme le SET, est de suivre les recommandation de 'AL1_24.

    Si les valeurs changent fréquemment et que vous avez besoin de les retrouver, vous ne devez pas les stocker mais les recalculer à l'aide d'une View.

    Cela vous aurait évité d'avoir à trouver une astuce pour résoudre votre problème.

    Cordialement.
    Artemus24.
    @+

  11. #11
    Expert éminent
    Avatar de Séb.
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    5 198
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 198
    Points : 8 421
    Points
    8 421
    Billets dans le blog
    17
    Par défaut
    L'astuce de Seb. fonctionne parfaitement, je l'ai testé, sauf qu'elle n'a pas la bonne syntaxe sous MySql :
    Si si, à condition que MySQL soit paramétré avec PIPES_AS_CONCAT
    Perso je suis en mode SET @@sql_mode = 'ANSI,TRADITIONAL'; ce qui est inclus l'option PIPES_AS_CONCAT

  12. #12
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 420
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 420
    Points : 19 228
    Points
    19 228
    Par défaut
    Salut Seb.

    Je suis dans le mode strict "innodb-strict-mode = on" et je n'ai pas modifié la variable "sql_mode" :
    Code mysql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    > select @@sql_mode;
    +-----------------------------------------------------------------------------------------------------------------------+
    | @@sql_mode                                                                                                            |
    +-----------------------------------------------------------------------------------------------------------------------+
    | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION |
    +-----------------------------------------------------------------------------------------------------------------------+
    1 row in set (0.00 sec)
     
    >

    Cordialement.
    Artemus24.
    @+

  13. #13
    Expert éminent
    Avatar de Séb.
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    5 198
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 198
    Points : 8 421
    Points
    8 421
    Billets dans le blog
    17
    Par défaut
    Avec @@sql_mode = 'ANSI,TRADITIONAL' :

    REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ONLY_FULL_GROUP_BY,ANSI,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_ENGINE_SUBSTITUTION

  14. #14
    Membre éclairé
    Avatar de clavier12AZQSWX
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Avril 2009
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Somme (Picardie)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : Avril 2009
    Messages : 1 418
    Points : 873
    Points
    873
    Par défaut
    plus haut, j'ai posé la question de l'existence ou non d'une fonction intégrée pour gérer les champs/colonnes contenant des valeurs de type liste de données (a,b,c,d) car dans ma précédent expérience avec Postgres, ça existait avec les fonctions sur les données tableau/array. (cf ARRAY_REMOVE)
    Depuis le temps, j'avais espéré que mysql avait un peu évolué...

  15. #15
    Expert éminent
    Avatar de Séb.
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    5 198
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 198
    Points : 8 421
    Points
    8 421
    Billets dans le blog
    17
    Par défaut
    Depuis le temps, j'avais espéré que mysql avait un peu évolué...
    Plus haut :
    Mysql n'a-t-il pas une fonction intégrée pour gérer les champs de type liste ?
    Or tu présentes une colonne de type TEXT avec des valeurs séparées par une , ; pour une colonne contenant des données structurées il y a JSON et ses tableaux/objets
    => https://dev.mysql.com/doc/refman/8.0/en/json.html

  16. #16
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 420
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 420
    Points : 19 228
    Points
    19 228
    Par défaut
    Salut à tous.

    @ clavier12AZQSWX : ta colonne n'est pas une liste de champs comme tu le dis.
    Tu détournes de sa fonction première le type SET ou ENUM pour en faire un usage différent.
    MySql fournit tout ce dont tu as besoin pour gérer ce type (SET ou ENUM) de colonne.

    Comme il a été dit plus haut, ta modélisation n'est pas correcte, d'où tes problèmes.
    La bonne façon de faire a été donnée par Al1_24.

    Cordialement.
    Artemus24.
    @+

Discussions similaires

  1. Réponses: 2
    Dernier message: 25/03/2019, 11h05
  2. Extraire un élément faisant partie d'une variable dans une regexp
    Par byrdo dans le forum Programmation et administration système
    Réponses: 9
    Dernier message: 17/04/2009, 15h21
  3. Afficher un partie d'une valeur dans un champ
    Par curt dans le forum VBA Access
    Réponses: 2
    Dernier message: 29/11/2007, 17h39
  4. Réponses: 13
    Dernier message: 18/05/2007, 16h06

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo