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

PL/SQL Oracle Discussion :

Comment supprimer un élément d'une loop ?


Sujet :

PL/SQL Oracle

  1. #1
    Battosaiii
    Invité(e)
    Par défaut Comment supprimer un élément d'une loop ?
    Bonjour,

    J'aimerais pouvoir supprimer la ligne rec (le premier résultat de la boucle)
    J'aimerais faire un delete de rec si rec a des champs egaux avec rec2.
    Voir le code ci dessous :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
     
    FOR rec IN ( select r.ID_DEMANDE,r.TYPE_EXAMEN, r.DATE_PRESCRIPTION
    			          from radiologie r
    			          where r.ID_EXAMEN LIKE '%*'
      )
      LOOP  
    		FOR rec2 IN ( select r.ID_DEMANDE,r.TYPE_EXAMEN, r.DATE_PRESCRIPTION
    					from radiologie r
    		)
    		LOOP
     
    			IF(rec2.ID_DEMANDE = rec.ID_DEMANDE,SUBSTR(rec.ID_EXAMEN,1,2)
    				and r3.TYPE_EXAMEN = rec.TYPE_EXAMEN
    				and r3.ID_EXAMEN LIKE '%*'
    				and TO_CHAR (r3.DATE_PRESCRIPTION, 'DD/MM/YYYY HH24:mi:ss')= TO_CHAR (rec.DATE_PRESCRIPTION, 'DD/MM/YYYY HH24:mi:ss');)
                            DELETE rec 
     
     
    		END LOOP;
     
       END LOOP;
    Comme vous le voyez j'aimerais supprimer rec si une condition est remplie. Je ne sais pas comment faire cela en SQL. COmment faire ceci en SQL ou PL :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    IF(rec2.ID_DEMANDE = rec.ID_DEMANDE,SUBSTR(rec.ID_EXAMEN,1,2)
    				AND r3.TYPE_EXAMEN = rec.TYPE_EXAMEN
    				AND r3.ID_EXAMEN LIKE '%*'
    				AND TO_CHAR (r3.DATE_PRESCRIPTION, 'DD/MM/YYYY HH24:mi:ss')= TO_CHAR (rec.DATE_PRESCRIPTION, 'DD/MM/YYYY HH24:mi:ss');)
                            DELETE rec

    Voici l'algorithme que je tente de reproduire :


    Pour chaque ligne de la table RADIOLOGIE dont ID_EXAMEN se termine par une étoile
    si pour le triplet T1 = [ ID_DEMANDE concaténé avec les 2 premiers caractères de ID_EXAMEN ; TYPE_EXAMEN ; DATE_PRESCRIPTION ]
    il existe une ligne de la table RADIOLOGIE dont le triplet T2 = [ ID_DEMANDE ; TYPE_EXAMEN ; DATE_PRESCRIPTION] est égal à T1
    alors supprimer la ligne (correspondant à T1, T2 étant une version plus récente du doublon)


    Merci
    Dernière modification par Battosaiii ; 27/05/2011 à 17h14.

  2. #2
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    2 952
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 2 952
    Par défaut
    Bizarre modèle, déjà il y a des doublons mais je ne comprends pas bien la logique derrière
    ID_DEMANDE concaténé avec les 2 premiers caractères de ID_EXAMEN
    Peut être comme ça, mais pas sûr, pense à rollback ou à te faire une table de backup :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    delete from radiologie r1
     where ID_EXAMEN LIKE '%*'
       and exists (select 1
                     from radiologie r2
                    where r2.DATE_PRESCRIPTION = r1.DATE_PRESCRIPTION
                      and r2.TYPE_EXAMEN = r1.TYPE_EXAMEN
                      and r2.ID_DEMANDE = r1.ID_DEMANDE||substr(ID_EXAMEN,1,2))

  3. #3
    Battosaiii
    Invité(e)
    Par défaut
    Ca marche ta fonction sur une table avec peu d'éléments.


    Par contre la requete prend trop de temps sur une base de 138 000 elements. Il me faut trouver une requete plus rapide.
    Dernière modification par Battosaiii ; 31/05/2011 à 11h26.

  4. #4
    Battosaiii
    Invité(e)
    Par défaut Comment supprimer rapidement les doublons d'une table avec 150 000 elements ?
    Bonjour,

    Comment supprimer les doublons de ma table ? Je vais appliquer les conditions de l'algo suivant pour supprimer les doublons de cette table :

    Pour chaque ligne de la table RADIOLOGIE dont ID_EXAMEN se termine par une étoile
    si pour le triplet T1 = [ ID_DEMANDE concaténé avec les 2 premiers caractères de ID_EXAMEN ; TYPE_EXAMEN ; DATE_PRESCRIPTION ]
    il existe une ligne de la table RADIOLOGIE dont le triplet T2 = [ ID_DEMANDE ; TYPE_EXAMEN ; DATE_PRESCRIPTION] est égal à T1
    alors supprimer la ligne (correspondant à T1, T2 étant une version plus récente du doublon)

    Voir la requete sql que j'ai trouvé : http://www.developpez.net/forums/d10...-element-loop/

    Malheureusement la requete SQL du lien precedent dure assez longtemps.+ de 10 minutes !!!

    J'aimerais trouver une requete SQL qui supprime les doublons tres vite.

    La table n'a pas de clé primaire. La clé primaire est formé avec 3 champs comme vous pouvez le voir sur l'algo d'en haut.

    Merci,





    Merci

  5. #5
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 454
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 454
    Par défaut
    Il faudrait fournir plus d'éléments pour vous aider sur la performance, pour commencer :
    • la volumétrie en nombre de lignes et en octets
    • la liste des index de votre table
    • le plan d'exécution de la requête de suppression

  6. #6
    Battosaiii
    Invité(e)
    Par défaut
    Salut,


    la volumétrie en nombre de lignes et en octets
    ->Il y a 180 000 lignes sur cette table.
    la liste des index de votre table
    -> Il y en a 1 seul index qui comprend la colonne NIP,ID_DEMANDE,TYPE_EXAMEN
    le plan d'exécution de la requête de suppression
    -> que voulez vous dire par la ?

  7. #7
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 454
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 454
    Par défaut
    En fait ça va être plutôt simple, vous n'allez pas faire de DELETE du tout !
    Supprimer 150.000 lignes sur 180.000, ce n'est pas intéressant, dans ces cas-là il vaut mieux recréer une nouvelle table avec les 30.000 données correctes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    CREATE TABLE radiologie_new
    TABLESPACE <votre_tbs>
    AS
    SELECT *
    FROM radiologie r1
     WHERE NOT (ID_EXAMEN LIKE '%*'
       AND EXISTS (SELECT 1
                     FROM radiologie r2
                    WHERE r2.DATE_PRESCRIPTION = r1.DATE_PRESCRIPTION
                      AND r2.TYPE_EXAMEN = r1.TYPE_EXAMEN
                      AND r2.ID_DEMANDE = r1.ID_DEMANDE||substr(ID_EXAMEN,1,2)));
     
    ALTER TABLE radiologie RENAME TO radiologie_old;
     
    ALTER TABLE radiologie_new RENAME TO radiologie;
    Puis recréez votre index et repositionnez les droits.
    Ce sera beaucoup plus rapide.

  8. #8
    Membre Expert Avatar de pacmann
    Homme Profil pro
    Consulté Oracle
    Inscrit en
    Juin 2004
    Messages
    1 626
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Consulté Oracle
    Secteur : Distribution

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 626
    Par défaut
    Salut !

    Le plan d'exécution, c'est ce qui permet de savoir comment Oracle exécute ta requête
    ... et donc ce qui peut permettre de comprendre pourquoi ça rame
    ... et donc éventuellement de trouver une solution.

    Tu exécutes dans SQL*Plus (par exemple) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    EXPLAIN PLAN FOR TaRequete
    Tu lances ensuite :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT * FROM TABLE(dbms_xplan.display)
    Il y a de fortes chances que ton index ne soit pas utiliser... après, s'il te fait un "filter" ou un truc du genre, ça peut expliquer la lenteur de l'exécution.

    Peut être poser un index sur (DATE_PRESCRIPTION,TYPE_EXAMEN,ID_DEMANDE)
    ?

  9. #9
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    2 952
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 2 952
    Par défaut
    Evidemment la proposition de Waldar est très bonne vue le pourcentage de lignes concerné, cependant cette soultion a un problème : il faut connaître le script des droits à réattribuer.

    Alors il est peut être possible de retrouver les droits en question via un export de table avec rows=n puis réimport dans un autre schema en précisant le paramêtre log.
    Mais pour savoir si ce mode de récupération des grants est total et pérenne il faudrait l'avis d'un dba.
    Il y a peut être d'autres moyens mais pareil un dba sera le bien venu pour préciser.

    Compte tenu de la volumétrie loin d'être excessive il me semble envisageable de quand même supprimer les lignes.
    Mais il est important pour de bonne perf avec le DELETE proposé de passer par un index à cause de la requête corrélée liée à EXISTS.
    Dans un 1er temps suit les conseils de Pacmann sinon essaie en modifiant l'ordre des colonnes dans l'index.

    Ou alors une version peut être plus fullscan friendly pour du 10g+ pourrait être :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    merge into radiologie r1
    using (SELECT DATE_PRESCRIPTION, TYPE_EXAMEN, ID_DEMANDE||substr(ID_EXAMEN,1,2) as id_dem
             FROM radiologie
          ) r2
       on (r1.DATE_PRESCRIPTION = r2.DATE_PRESCRIPTION AND r1.TYPE_EXAMEN = r2.TYPE_EXAMEN AND r1.ID_DEMANDE = r2.id_dem)
     when matched then delete
    where r1.ID_EXAMEN LIKE '%*'
    Sinon quel est le type de donnée de ID_DEMANDE ? varchar2 ou number ?

  10. #10
    Battosaiii
    Invité(e)
    Par défaut
    Merci pour vos réponses.

    Voici la solution que j'ai adopté. J'ai trouvé une clé primaire temporaire rowid.
    J'ai supprimé les éléments à partir de rowid.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    delete from radiologie where radiologie.rowid
    in
    (
    select radio2.rowid
     from radiologie radio1,radiologie radio2, fus@db_gip
    where radio1.id_demande = radio2.id_demande
    and radio1.type_examen = radio2.type_examen
    and radio1.nip <> radio2.nip
    and radio1.nip = nipact
    and radio2.nip = nipfus
    )

Discussions similaires

  1. Comment supprimer un élément d'une ListView ?
    Par xXO--Hades--OXx dans le forum Composants graphiques
    Réponses: 5
    Dernier message: 12/12/2010, 16h57
  2. Réponses: 7
    Dernier message: 16/05/2006, 15h40
  3. Supprimer un élément d'une TObjectList
    Par Lung dans le forum Langage
    Réponses: 15
    Dernier message: 30/05/2005, 17h32
  4. Réponses: 17
    Dernier message: 18/03/2005, 15h56
  5. Réponses: 14
    Dernier message: 15/01/2004, 01h15

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