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

Langage SQL Discussion :

Delete avec sous-requête synchronisée


Sujet :

Langage SQL

  1. #1
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 5
    Points : 1
    Points
    1
    Par défaut Delete avec sous-requête synchronisée
    Bonjour,

    Je n'arrive pas à trouver la bonne syntaxe pour effectuer un delete avec sous-interrogation synchronisée. La requête suivante est refusée, ce qui est bien dommage pour moi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     DELETE FROM message
    WHERE cle IN (SELECT cle FROM message AS tbl
        WHERE date  < (SELECT MAX(date) FROM message 
             WHERE composant = tbl.composant))
    La même requête avec un "select * " à la place du "delete" fonctionne.

    La table contient un historique de messages portant sur des composants. Je veux nettoyer l'historique pour ne garder que le dernier message relatif à chaque composant. Comment faire ?

    Désolé s'il s'agit d'une question de débutant car c'est bien mon cas, mais je n'ai pas trouvé l'info par ailleurs...

    (mysql 5)

  2. #2
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 862
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 862
    Points : 53 013
    Points
    53 013
    Billets dans le blog
    6
    Par défaut
    Votre requête est synatxiquement parfaite et il n'y a a priori aucun problème (sauf erreur de colonnes , mais vous n'avez pas mentionné la structure des tables... dommage).
    Il est probable qu'il s'agisse d'une limitation de MySQL qui implémente très mal les sous requêtes...

    A +

  3. #3
    Membre averti Avatar de icsor
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2008
    Messages
    258
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Distribution

    Informations forums :
    Inscription : Mai 2008
    Messages : 258
    Points : 436
    Points
    436
    Par défaut
    Bonjour,

    je ne connais pas MySQL, donc ne sais pas si votre requête peut être accepté par ce SGBD, mais pour moi, il y a un problème de sens.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     (SELECT cle FROM message AS tbl
        WHERE date  < (SELECT MAX(date) FROM message 
             WHERE composant = tbl.composant))
    Pour moi, ce code renvoi toutes les identifiant "cle" qui ont au moins deux dates différentes dans votre table. Et vous essayez donc d'effacer toutes les lignes donctenant ces cle, pas seulement celles qui ont les cates les plus anciennes.

    Personnellement, je verrai plus un truc du genre:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    DELETE FROM message AS m1
    WHERE EXISTS (SELECT 1 
    FROM message AS m2 
    WHERE m1.cle = m2.cle AND m1.date < m2.date)

  4. #4
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 5
    Points : 1
    Points
    1
    Par défaut
    Désolé de ne pas avoir donné le structure de la table (une seule impliquée). Comme je pensais qu'il s'agissait d'un problème de syntaxe, je croyais qu'indiquer que la même requête fonctionnait avec un "select *" à la place du "delete" était suffisant. Promis, je ne le ferai plus

    Je vais explorer la piste des limitations MySQL en testant des exemples de tutoriels de "delete" avec sous-requêtes ordinaires. Mais je n'en ai pas trouvé qui utilisent les sous-requêtes synchronisées. J'ai l'impression que c'est cette particularité qui bloque...

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    CREATE TABLE IF NOT EXISTS message (
      `date` int(11) NOT NULL,
      `composant` varchar(40) NOT NULL,
      `code` smallint(6) NOT NULL,
      `cle` int(11) NOT NULL auto_increment,
      PRIMARY KEY  (`cle`)
    ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=12 ;

  5. #5
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 5
    Points : 1
    Points
    1
    Par défaut
    Citation Envoyé par icsor Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     (SELECT cle FROM message AS tbl
        WHERE date  < (SELECT MAX(date) FROM message 
             WHERE composant = tbl.composant))
    Pour moi, ce code renvoi toutes les identifiant "cle" qui ont au moins deux dates différentes dans votre table. Et vous essayez donc d'effacer toutes les lignes donctenant ces cle, pas seulement celles qui ont les cates les plus anciennes.
    Merci pour cette piste mais cette partie de la requête fait bien ce que j'en attends : sélectionner toutes les lignes sauf celles qui, pour une cle donnée, a la valeur max dans la colonne date.

  6. #6
    Membre averti Avatar de icsor
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2008
    Messages
    258
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Distribution

    Informations forums :
    Inscription : Mai 2008
    Messages : 258
    Points : 436
    Points
    436
    Par défaut
    Dis moi comment identifie tu deux lignes de ton résultat avec une même cle mais une date différente si tu ne renvoies que la cle ?

  7. #7
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 5
    Points : 1
    Points
    1
    Par défaut
    Citation Envoyé par icsor Voir le message
    Dis moi comment identifie tu deux lignes de ton résultat avec une même cle mais une date différente si tu ne renvoies que la cle ?
    Oupss... J'ai répondu trop vite. Il fallait lire "pour un composant donné" et non "pour une clé donnée". Le prédicat portant sur le composant :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    WHERE composant = tbl.composant

  8. #8
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 5
    Points : 1
    Points
    1
    Par défaut
    Citation Envoyé par SQLpro Voir le message
    ...
    Il est probable qu'il s'agisse d'une limitation de MySQL qui implémente très mal les sous requêtes...
    Est-ce une limitation de MySQL ou une erreur du tutoriel, toujours est-il que la requête suivante, adaptée du tuto, est refusée par MySQL :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    SELECT * FROM T_PROSPECT
    WHERE  PRP_ID = (SELECT PRP_ID
                     FROM   T_PROSPECT P
                            JOIN T_CLIENT C 
                                 ON C.CLI_NOM = P.PRP_NOM
                                AND C.CLI_PRENOM = P.PRP_PRENOM)

    "WHERE PRP_ID = (SELECT PRP_ID ..." est refusé car la requête imbriquée renvoie plusieurs lignes, comme cela est d'ailleurs souhaité. Un "IN" semblerait plus approprié. Non ?

    Une fois ce détail corrigé, ce type de requête est refusé, comme celle que je présentais au début. Après des recherches, j'ai trouvé une réponse au "pourquoi c'est refusé" (doc MySQL) :

    You can use a subquery for assignment within an UPDATE statement because subqueries are legal in UPDATE and DELETE statements as well as in SELECT statements. However, you cannot use the same table (in this case, table t1) for both the subquery's FROM clause and the update target.

    Mais ça ne me dit pas comment faire Y a-t-il une ruse pour obtenir le résultat souhaité ou dois-je renoncer à l'obtenir en une seule requête ?

  9. #9
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 102
    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 102
    Points : 28 401
    Points
    28 401
    Par défaut
    La ruse serait de passer par une table temporaire qui enregistre les identifiants des lignes à supprimer

  10. #10
    Membre averti Avatar de icsor
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2008
    Messages
    258
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Distribution

    Informations forums :
    Inscription : Mai 2008
    Messages : 258
    Points : 436
    Points
    436
    Par défaut
    Ou bien, tu peux passer par un alias de table pour ta requète.

Discussions similaires

  1. Requête DELETE avec sous requête
    Par El-Toro dans le forum Requêtes
    Réponses: 4
    Dernier message: 27/06/2008, 22h39
  2. Erreur syntaxe SQL DELETE avec sous requête
    Par jeanbenoit1987 dans le forum Langage SQL
    Réponses: 6
    Dernier message: 07/12/2007, 12h14
  3. DELETE avec sous-requête
    Par say dans le forum Langage SQL
    Réponses: 2
    Dernier message: 27/04/2005, 08h20
  4. INTERBASE: DELETE avec sous requete conditionnelle
    Par Papino dans le forum InterBase
    Réponses: 6
    Dernier message: 17/02/2005, 22h55
  5. suppression avec sous requête conditionnelle
    Par melmel dans le forum Requêtes
    Réponses: 8
    Dernier message: 18/03/2004, 23h20

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