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

PHP & Base de données Discussion :

Supprimer une donnée particulière [Fait] [MySQL]


Sujet :

PHP & Base de données

  1. #1
    Membre confirmé Avatar de Ricou13
    Inscrit en
    Août 2002
    Messages
    292
    Détails du profil
    Informations forums :
    Inscription : Août 2002
    Messages : 292
    Par défaut Supprimer une donnée particulière
    Bonsoir,

    Voici mon problème :

    J'ai une base de données avec une table "users".
    Cette table contient un champ texte "parking" qui contient une série de nombres séparés par des virgules : 12,5,165,78,1,51...

    Ces nombres sont uniques (ce sont des id). Parce que l'utilisation et la gestion de cette liste était simple (à la base), nous avons opté pour un champ plutot qu'une table associative.

    Bref, je recherche une solution me permettant de "balayer" la table "users" et de retirer un nombre en particulier de tous les champs parking.

    Par exemple : je voudrais retirer tous les nombres "165"

    J'ai cependant quelques contraintes :

    - Je pourrais évidemment lire chaque enregistrement de la table, rechercher si le champ "parking" contient le nombre, le supprimer et faire un UPDATE => cela me semble plus que particulièrement lourd sachant que la table pourrait contenir plusieurs milliers de lignes.

    - Je dois faire attention à supprimer un nombre en entier et pas une partie d'un autre. Ex: si je supprimer le nombre "1", je ne dois pas enlever le chiffre "1" des nombres "12", "165" et "51" de l'exemple ci-dessus.

    - Le champ peut contenir de 0 à n nombre (heureusement donc, tous différents). De fait, si on passe par une regexp, elle doit prendre en compte que le nombre peut être seul, en premier, au millieu, en dernier ou ne pas y être.

    - il faut essayer d'optimiser le temps de traitement

    A la limite, même si elle est un peu barbare, je dois pouvoir m'en sortir avec la regexp (enfin j'éspère) mais je ne vois pas du tout comment traiter ce pb.

    Merci de votre aide.

  2. #2
    Membre expérimenté

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    6 152
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 6 152
    Par défaut
    Des fonctions comme FIND_IN_SET() pour le SGBD MySQL pourrait vous aider en ne retournant uniquement les lignes qui doivent être modifiées mais il devrait être incapable d'effectuer les traitements sans PHP.

    Note : la fonction citée ne fonctionne seulement dans le cas particulier ou les éléments sont numériques et le séparateur est une virgule.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    $query = mysql_query('SELECT * FROM ma_table WHERE FIND_IN_SET(la_valeur_numérique_cherchée, champ_sous_forme_de_liste) <> 0;');
    while ($array = mysql_fetch_assoc($query)) {
        $ids = explode(',', $array['champ_sous_forme_de_liste']);
        unset($ids[array_search(la_valeur_numérique_cherchée, $ids)]);
        mysql_query("UPDATE ma_table SET champ_sous_forme_de_liste = '" . implode(',', $ids) . "' WHERE ...");
    }
    Testé sur un petit exemple.

  3. #3
    Membre confirmé Avatar de Ricou13
    Inscrit en
    Août 2002
    Messages
    292
    Détails du profil
    Informations forums :
    Inscription : Août 2002
    Messages : 292
    Par défaut
    Salut,

    Merci pour ta réponse. Entre temps, j'ai découvert que MySQL gérait les expressions régulières.

    J'ai donc pondu ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    $X = la_valeur_cherchée;
    $strSQL = 'SELECT Id, Parking FROM users  
    WHERE Parking REGEXP "(^' . $X . '$)|(^' . $X . ',)|(,' . $X . ',)|(,' . $X . '$)"';
     
    $rsParkings = mysql_query($strSQL) or die( '<br />Erreur sur la requete (ligne ' . __LINE__ . ') : ' . mysql_error() . '<br />' );
    Ce qui, pour une recherche sur le nombre 8 me donne
    ...WHERE Parking REGEXP "(^8$)|(^8,)|(,8,)|(,8$)
    Cela fonctionne très bien mais je vais plutôt utiliser ta méthode car elle est beaucoup plus simple à comprendre (pour la maintenance) et qu'elle élimine tout risque de combinaison oubliée (pas dans ce cas précis mais en général)

    Pour la suite, comme il est possible de faire des "agrégats" de VALUES pour un seul INSERT
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $SQL = 'INSERT INTO xxx VALUES(...), VALUES(...), VALUES(...), ...'
    J'avais espéré pouvoir faire un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $SQL = 'UPDATE users
    (SET Parking = "xxx" WHERE Id = 12), (SET Parking = "yyy" WHERE Id = 52), (SET Parking = "zzz" WHERE Id = 67), ...'
    Mais ça marche pô

    Je dois donc effectuer une boucle de traitement, certes plus rapide puisque seules les lignes concernées ont été remontées par la requête mais, bon...

    Et là, j'ai un soucis avec mon expression régulière qui va "nettoyer" la liste (une regexp me semble beaucoup plus rapide qu'un explode suivi d'un unset et d'un implode)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $Pattern = '`(^' . $Id . '$)|(^' . $Id . ',)|,(' . $Id . ',)|(,' . $Id . '$)`';
    // Nettoyage
    $NewParking = preg_replace($Pattern, '', $rowParkings['Use_Parking']);
    Le 3ème cas (où le nombre recherché se trouve en plein milieu - celui en gras et rouge) ne devrait me supprimer qu'une seule des 2 virgules. Or, dans mon cas, les 2 sont supprimées et les 2 nombres de chaque coté sont collés.

    Voici un exemple de code traitant les 4 cas de positionnement possible du nombre recherché (seul, en premier, en dernier, au milieu)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
      $Id = 8;
      $tPak = array('8,1,11,22', '22,8', '8', '1,8,13');
      $Pattern = '`(^' . $Id . '$)|(^' . $Id . ',)|,(' . $Id . ',)|(,' . $Id . '$)`';
      for($i = 0; $i < 4; $i++)
        $tPak[$i] = preg_replace($Pattern, '', $tPak[$i]);
     
      print_r($tPak);
    Ce code qui devrait me retourner
    array('1,11,22', '22', '', '1,13');
    me retourne, en fait
    array('1,11,22', '22', '', '113');
    La seconde virgule à disparu !

  4. #4
    Membre expérimenté

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    6 152
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 6 152
    Par défaut
    Vous ne retrouvez pas la deuxième virgule car elle est consommée par l'expression régulière :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    $Id = 8;
    $tPak = array('8,1,11,22', '22,8', '8', '1,8,13');
    $Pattern = "`^$Id$|^$Id,|,$Id(,)|,$Id$`";
    for($i = 0; $i < 4; $i++)
      $tPak[$i] = preg_replace($Pattern, '\1', $tPak[$i]);
     
    print_r($tPak);
    Note : vos parenthèses, dans le code précédent, sont inutiles d'autant plus qu'elles seront utilisées pour procéder à la capture de la partie de la chaîne correspondante alors que celles-ci ne seront pas ensuite réemployées dans le paramètre replacement de la fonction preg_replace.

    Quant à la solution, je vous laisse bien évidemment le soin de tester et/ou de faire votre choix (selon vos propres critères).

  5. #5
    Membre confirmé Avatar de Ricou13
    Inscrit en
    Août 2002
    Messages
    292
    Détails du profil
    Informations forums :
    Inscription : Août 2002
    Messages : 292
    Par défaut
    Magnifique

    J'utilisais les parenthèses dans le sens : "je précise ce qui doit être remplacé"
    C'était donc le sens contraire qu'il fallait utiliser.

    En plus j'ai appris 2 choses :

    - Si les parenthèse ne sont pas réutilisées, c'est comme si elles n'étaient pas là.
    - Je ne pensais pas qu'il était possible, dans une même regexp, d'indiquer plusieurs fois la notion de "début"(^) ou "fin"($) de chaine.

    Je suppose que l'anti-slash sur le dernier "$" est pour indiquer qu'il est lié au 4eme cas et n'est pas global.

    Merci

  6. #6
    Membre expérimenté

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    6 152
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 6 152
    Par défaut
    Citation Envoyé par Ricou13
    J'utilisais les parenthèses dans le sens : "je précise ce qui doit être remplacé"
    C'était donc le sens contraire qu'il fallait utiliser.
    Tout ce qui figure dans le motif (premier paramètre de la fonction) sera remplacé, parenthèses ou non. La capture est un moyen d'en refaire apparaître une partie.

    Citation Envoyé par Ricou13
    - Si les parenthèse ne sont pas réutilisées, c'est comme si elles n'étaient pas là.
    Si vous faites allusion à la capture : les données relatives à la capture bien qu'inutilisées doivent être gardées en mémoire jusqu'au remplacement. Vous avez tout à fait le droit d'utiliser des parenthèses pour faciliter la lecture mais il est alors intéressant d'ajouter juste après la parenthèse ouvrante ?: afin de les rendre non capturantes. (Ceci est expliqué dans le tutoriel d'initiation aux expressions régulières en PHP).

    Citation Envoyé par Ricou13
    - Je ne pensais pas qu'il était possible, dans une même regexp, d'indiquer plusieurs fois la notion de "début"(^) ou "fin"($) de chaine.
    C'est le but d'une alternative Ces ancres n'auraient effectivement pas de sens sinon en plein milieu de l'expression - il existe quand même une exception : si on utilise l'option m(ultiline) (voir ici).

    Citation Envoyé par Ricou13
    Je suppose que l'anti-slash sur le dernier "$" est pour indiquer qu'il est lié au 4eme cas et n'est pas global.
    J'ai oublié de l'enlever celui-là mais ce n'est pas grave : je les avais mis au départ pour être sûr que PHP ne cherchent pas interpoler (remplacer une variable par sa valeur), ayant changé le délimiteur de la chaîne correspondant au motif pour y voir plus clair.

  7. #7
    Membre confirmé Avatar de Ricou13
    Inscrit en
    Août 2002
    Messages
    292
    Détails du profil
    Informations forums :
    Inscription : Août 2002
    Messages : 292
    Par défaut
    On en apprend tous les jours

    Par contre, j'ai maintenant un soucis avec mes updates.
    Si je modifie plusieurs lignes sous phpMyAdmin, le système m'affiche une requête du type
    UPDATE ... LIMIT 1;
    UPDATE ... LIMIT 1;
    UPDATE ... LIMIT 1;
    ...
    Partant de ce principe, j'ai donc décidé de ne créer qu'une seule chaine SQL, contenant tous mes UPDATE afin de réduire au minimum les accès serveurs.

    J'ai donc créé une chaine qui, au final, me donne ceci
    UPDATE users SET Parking = "1,11,22" WHERE Id = 5; UPDATE users SET Parking = "" WHERE Id = 7; UPDATE users SET Parking = "22" WHERE Id = 8;...
    c'est cette chaine que j'envoie via un mysql_query.

    Mais, là, j'ai une erreur de syntaxe au niveau du premier ";"
    Or, si je copie la chaine et que je la colle dans phpMyAdmin, le traitement s'effectue sans problème.

    ???

  8. #8
    Membre confirmé Avatar de Ricou13
    Inscrit en
    Août 2002
    Messages
    292
    Détails du profil
    Informations forums :
    Inscription : Août 2002
    Messages : 292
    Par défaut
    A force d'utiliser des fonctions, on finit par ne plus lire la doc :
    mysql_query
    [...]
    query
    Une requête SQL

    La chaîne de requête ne doit pas se terminer par un point-virgule.
    Je suis donc condamné à faire mes UPDATES un par un, me semble-t-il

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Supprimer une donnée (Hsupprime)
    Par skulled dans le forum WinDev
    Réponses: 4
    Dernier message: 29/07/2007, 13h22
  2. Supprimer une donnée et toutes ses références
    Par calagan99 dans le forum Langage SQL
    Réponses: 4
    Dernier message: 04/06/2007, 15h41
  3. [Configuration] Supprimer une donnée dans un fichier
    Par cirtey dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 8
    Dernier message: 07/02/2007, 16h36
  4. Supprimer une donnée d'un fichier txt
    Par dinastar dans le forum Langage
    Réponses: 7
    Dernier message: 31/03/2006, 15h28

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