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 :

delete avec sql dynamique


Sujet :

PL/SQL Oracle

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    254
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 254
    Par défaut delete avec sql dynamique
    Bonjour à tous,

    Je voudrais faire un script qui va deleter les données de toutes les tables de ma base selon certaines conditions.

    J'utilise un curseur pour récupérer les noms des tables (pour optimiser la maintenance vu que je sais pas on va ajouter ou supprimer des tables dans le futur).

    Ensuite dans ma boucle je pose une variable de type varchar qui sera le contenu de ma requête, que j'exécute ensuite via un "execute immediate".

    Mon problème : ça ne marche pas! (lol)
    Pour entrer dans les détails : quand il n'y a aucune donnée dans les tables : ça passe nickel. (tu m'étonnes!) Le script se termine et tout va bien.
    Mais quand on a des données (environ 500 000 lignes) ça mouline dans le vide et il ne delete rien.

    Voici mon code :
    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
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
     
    CREATE OR REPLACE PROCEDURE BOS.Suppression_des_erreurs_BOS 
        ( 
        p_DateFonc IN VARCHAR2,
        p_IDProvenance IN INTEGER
        ) IS
     
     
        CURSOR c_NomTable IS            --Curseur qui récupère le nom de toutes les tables de la base BOS        
            SELECT TABLE_NAME        
            FROM ALL_TABLES         
            WHERE OWNER='BOS';
     
        l_NomTable c_NomTable%ROWTYPE;  --Ligne de lecture du curseur  
     
        v_DateFonc varchar2(10);        --Date à supprimer en paramètre
        v_IDProvenance varchar2(10);    --ID Provenance
        v_Requete varchar2(500);        --Chaine de requête SQL dynamique
     
     
     
     
        BEGIN
     
            v_DateFonc := p_DateFonc;
            v_IDProvenance := TO_CHAR(p_IDProvenance);
     
            OPEN c_NomTable;            --Ouverture du curseur
     
            LOOP
                FETCH c_NomTable INTO l_NomTable;
                EXIT WHEN c_NomTable%NOTFOUND; --Sortir à la fin du curseur
     
                v_REQUETE := 'DELETE FROM ' || l_NomTable.TABLE_NAME || 
                             ' WHERE DAT_MAJ_PHT >=''' || v_DateFonc ||
                             ''' AND ID_PROVENANCE =''' || v_IDProvenance || '''';
                EXECUTE IMMEDIATE v_REQUETE;
            END LOOP;
     
            CLOSE c_NomTable;           --Fermeture du curseur
     
        END;
    /
    Merci de votre aide

  2. #2
    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
    Est-ce que vous avez des triggers et des index ?

    Est-ce que vos tables sont indexées sur les colonnes du delete (DAT_MAJ_PHT, ID_PROVENANCE) ?

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    254
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 254
    Par défaut
    Oui effectivement j'ai des index sur ces deux champs. Est ce que ça peut jouer?

  4. #4
    Invité de passage
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    1
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juin 2010
    Messages : 1
    Par défaut formatage de la date
    Lorsque tu convertis ton paramètre p_IDProvenance, j'ajouterais un format qui correspondrait à celui de la table.

    Par exemple,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    v_IDProvenance := 
             TO_CHAR(p_IDProvenance, 'YYYY-MM-DD');

  5. #5
    Expert confirmé
    Avatar de SheikYerbouti
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    6 760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 6 760
    Par défaut
    Attention aux dates, c'est basique.

    Vos variables sont en VARCHAR, il faut donc faire une conversion en date avant de comparer. De plus To_Char() sir une variable CHAR n'est pas la solution. Il faut utiliser To_Date() et comparer avec la colonne DATE de la base.

  6. #6
    McM
    McM est déconnecté
    Expert confirmé

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Billets dans le blog
    4
    Par défaut
    1/ Mieux vaut utiliser des bind variables.

    2/ Les colonnes id_provenance sont en VARCHAR2 ou en NUMBER ?
    Parce qu'il ne faut pas forcer la base à faire du cast.

    3/ Tu ne commites pas dans la boucle ? Ton Undo est suffisant pour absorber le delete

  7. #7
    Membre éclairé
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    254
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 254
    Par défaut
    Bonjour,

    Merci à vous pour toutes vos réponses.

    Alors pour répondre à vos questions :
    ID_PROVENANCE est un INTEGER dans toutes mes tables. Et dans la procédure je le déclare en tant qu'INTEGER.

    Sinon effectivement le bind variable que je ne connaissais pas m'a permis de réduire efficacement le temps d'exécution. Un grand merci donc!

  8. #8
    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
    N'hésitez pas à mettre le nouveau code, ça servira pour les recherches !

  9. #9
    Membre éclairé
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    254
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 254
    Par défaut
    Voici mon code :

    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
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
     
    CREATE OR REPLACE PROCEDURE BDM.suppression_des_erreurs_BDM (
       p_datefonc       IN   VARCHAR2,
          --Paramètre 1 : date à partir de laquelle on supprime toutes les données
       p_idprovenance   IN   INTEGER
                           --Paramètre 2 : ID du site dont on supprime les données
    )
    IS
    /*
    Déclaration des variables
    */
     
       --Curseur qui récupère le nom de toutes les tables de la base BDM
       CURSOR c_nomtable
       IS
          SELECT table_name
            FROM all_tables
           WHERE owner = 'BDM';
     
       l_nomtable       c_nomtable%ROWTYPE;         --Ligne de lecture du curseur
       v_datefonc       VARCHAR2 (10);            --Date à supprimer en paramètre
       v_idprovenance   VARCHAR2 (10);               --ID Provenance en paramètre
       v_requete        VARCHAR2 (5000);        --Chaine de requête SQL dynamique
    /*
    Corps de la procédure
    */
    BEGIN
       v_datefonc := TO_DATE (p_datefonc, 'DD/MM/YYYY');
       v_idprovenance := p_idprovenance;
     
       OPEN c_nomtable;                                    --Ouverture du curseur
     
       LOOP
          FETCH c_nomtable
           INTO l_nomtable;
     
          EXIT WHEN c_nomtable%NOTFOUND;             --Sortir à la fin du curseur
          v_requete :=                         --Création de la requête dynamique
                'DELETE FROM '
             || l_nomtable.table_name
             || ' WHERE DAT_MAJ_PHT >=:v_tmp1 AND ID_PROVENANCE =:v_tmp2';
     
          EXECUTE IMMEDIATE v_requete
                         --Exécution de la requête avec un bind multiple variables
                      USING v_datefonc, v_idprovenance;
     
          --Message de confirmation à chaque suppression de données dans une table
          DBMS_OUTPUT.put_line ('Table ' || l_nomtable.table_name || ' nettoyee.');
       END LOOP;
     
       CLOSE c_nomtable;                                    --Fermeture du curseur
     
       COMMIT;
    END;
    /

  10. #10
    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
    Merci pour les suivants.

    Une dernière remarque, pourquoi ne pas directement typer p_datefonc en date ?
    Vous pourriez directement utiliser vos paramètres au lieu de passer par deux variables.

  11. #11
    McM
    McM est déconnecté
    Expert confirmé

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Billets dans le blog
    4
    Par défaut
    Le code est pas mal, mais il reste des erreurs et quelques optis possible
    Les erreurs : v_datefonc est une date ou une chaine ?
    v_idprovencance : Integer ou Chaine ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    v_datefonc       VARCHAR2 (10);  
    v_datefonc := TO_DATE (p_datefonc, 'DD/MM/YYYY');
     
    p_idprovenance   IN   INTEGER
    v_idprovenance   VARCHAR2 (10);   
    v_idprovenance := p_idprovenance;
    Voici un code avec la solution de waldar + mes optis (simplification de curseur)
    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
    23
    24
    25
    26
    27
    28
    29
    CREATE OR REPLACE PROCEDURE BDM.suppression_des_erreurs_BDM (
       p_datefonc       IN   DATE,    --Paramètre 1 : date à partir de laquelle on supprime toutes les données
       p_idprovenance   IN   INTEGER      --Paramètre 2 : ID du site dont on supprime les données
    )
    IS
       v_requete        VARCHAR2 (5000);        --Chaine de requête SQL dynamique
    BEGIN
     
       --Curseur qui récupère le nom de toutes les tables de la base BDM
       FOR l_nomtable IN (SELECT table_name
            FROM all_tables
           WHERE owner = 'BDM') 
       LOOP
     
          v_requete :=                         --Création de la requête dynamique
                'DELETE FROM '
             || l_nomtable.table_name
             || ' WHERE DAT_MAJ_PHT >=:v_tmp1 AND ID_PROVENANCE =:v_tmp2';
     
          --Exécution de la requête avec un bind multiple variables
          EXECUTE IMMEDIATE v_requete USING p_datefonc, p_idprovenance;
     
          --Message de confirmation à chaque suppression de données dans une table
          DBMS_OUTPUT.put_line ('Table ' || l_nomtable.table_name || ' nettoyee.');
       END LOOP;
     
       COMMIT;
    END;
    /

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

Discussions similaires

  1. Fonction avec SQL 'dynamique'
    Par gillou13 dans le forum Développement
    Réponses: 3
    Dernier message: 24/08/2011, 10h08
  2. Procédure PL/SQL avec sql dynamique
    Par Fiona08 dans le forum PL/SQL
    Réponses: 5
    Dernier message: 10/12/2010, 14h50
  3. ORA-00904 avec SQL dynamique
    Par pascal_T dans le forum PL/SQL
    Réponses: 10
    Dernier message: 10/10/2008, 14h46
  4. Créer une vue avec du SQl dynamique
    Par gghonang2 dans le forum Oracle
    Réponses: 15
    Dernier message: 06/09/2006, 22h03
  5. Delete on cascade avec SQL server
    Par fadoua dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 14/01/2004, 11h02

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