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

SQL Oracle Discussion :

[PL/SQL][Oracle9i] comment faire un commit tous les n updates ?


Sujet :

SQL Oracle

  1. #1
    Futur Membre du Club
    Inscrit en
    Septembre 2006
    Messages
    8
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 8
    Points : 5
    Points
    5
    Par défaut [PL/SQL][Oracle9i] comment faire un commit tous les n updates ?
    Bonjour et bravo pour ce site, je sens qu'il me sera tres utile a l'avenir

    Mon problême est assez simple en fait .
    Dans une procédure stockée j'ai un cruseur qui récupère le nom de différentes tables que je dois mettre a jours . Par exemple je récupère tous les noms de tables ayant la colonne 'PAC' .
    Le but c'est de mettre a jour les valeurs de 'PAC' dans toutes ces tables .

    exemple :
    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
     
    CREATE OR REPLACE PROCEDURE MAJ_PAC
    (p_new_pac IN varchar2, p_old_pac in varchar2 )
    IS
     
    cursor c1 is select table_name from user_tab_columns a, user_objects b 
    where a.column_name='PAC' and a.table_name=b.object_name 
    and b.object_type='TABLE';
     
    var1 c1%rowtype;
    req varchar2(200);
     
    BEGIN
     
    open c1;
    loop
        fetch c1 into var1;
        exit when c1%NOTFOUND;
        req := 'update '||var1.table_name||' set PAC = '||p_new_pac ||
        'where PAC = '||p_old_pac;
        EXECUTE IMMEDIATE req;
        commit;   
    end loop;
    close c1;
     
    END;
    Avec ce systeme ma procedure fait un commit apres chaque table updaté, mon probleme c'est que je ne sais pas a l'avance combien de lignes seront modifiés dans chaque table, ce que je voudrais obtenir c'est par exemple un commit sur ma table dès qu'on a atteint 500 000 lignes modifiés .
    Parce que là parfois ma procédure fait un commit apres un update qui impact 16 millions de lignes d'une table, et les rollback segment enflent et le dba devient tout rouge et vient crier dans mon bureau

    Merci d'avance !

  2. #2
    Membre expert
    Avatar de LeoAnderson
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    2 938
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 2 938
    Points : 3 199
    Points
    3 199
    Par défaut
    Bonjour et bienvenue !

    La règle de base ici est de ne poster qu'après avoir cherché (cf "A lire avant de poster").

    Sur ce même forum, il y a un topic "Comment faire un commit intermédiaire".... ;-)

  3. #3
    Futur Membre du Club
    Inscrit en
    Septembre 2006
    Messages
    8
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 8
    Points : 5
    Points
    5
    Par défaut
    Citation Envoyé par LeoAnderson
    Sur ce même forum, il y a un topic "Comment faire un commit intermédiaire".... ;-)
    oui merci j'ai vu avant de poster, mais le contexte n'est pas du tout le meme car dans le topic dont vous parlez il s'agit de faire un insert de valeurs retournés par un select, donc on peut eventuellement utiliser le rownum (meme si apparement c'est tres déconseillé au niveau perf) . Dans mon cas je ne peux pas utiliser de rownum (et comme de toutes façon c'est pas la bonne solution ...).

  4. #4
    Membre éprouvé
    Inscrit en
    Avril 2006
    Messages
    1 024
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 1 024
    Points : 1 294
    Points
    1 294
    Par défaut
    tu peux capter une variable PL/SQL juste après ton EXECUTE, elle s'appelle SQL%ROWCOUNT. Elle te donne le nombre exact de ligne modifiées, donc apres ça tu peux par exemple programmer pour accumuler cette variable dans un compteur général et commiter quand tu atteint un certain seuil.

    Cependant tu ne pourra pas insérer un commit intermédiaire au milieu de ta requête d'update si celle si fait 16M de modif en une seule fois...

  5. #5
    Membre expert

    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Janvier 2004
    Messages
    2 862
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 862
    Points : 3 609
    Points
    3 609
    Par défaut
    Citation Envoyé par Phénélas
    Dans mon cas je ne peux pas utiliser de rownum (et comme de toutes façon c'est pas la bonne solution ...).
    Moi au contraire dans ton cas je pense que c'est la bonne solution:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    open c1;
    loop
        fetch c1 into var1;
        exit when c1%NOTFOUND;
        req := 'update '||var1.table_name||' set PAC = '||p_new_pac ||
        'where PAC = '||p_old_pac || ' and rownum < 50000';
        loop
           EXECUTE IMMEDIATE req;
           commit;    
        exit when sql%notfound;
        end loop;
    end loop;
    close c1;
    Un problème sans solution est un problème mal posé

    Merci de poser vos questions sur le forum, je ne réponds pas aux questions posées par MP.

  6. #6
    Membre éprouvé
    Inscrit en
    Avril 2006
    Messages
    1 024
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 1 024
    Points : 1 294
    Points
    1 294
    Par défaut
    Citation Envoyé par plaineR
    Moi au contraire dans ton cas je pense que c'est la bonne solution:
    Bien vu, pour cette requête effectivement, y'a aucun problème vu que la clause where élimine forcément les ligne modifiées précédemment....

    Juste un cas particulier, verifier que p_old_pac soit bien différent de p_new_pac

  7. #7
    Futur Membre du Club
    Inscrit en
    Septembre 2006
    Messages
    8
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 8
    Points : 5
    Points
    5
    Par défaut
    Merci pour votre aide précieuse, je suis désolé je ne suis pas (encore) tres calé en pl/sql mais dans l'exemple donné par plaineR il me semble que seulement 50 000 enregistrements sont modifiés (rownum<50000) mais si ma table en contient plusieurs millions comment modifier les enregistrements compris entre 50 001 et x millions ?

  8. #8
    Membre expert

    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Janvier 2004
    Messages
    2 862
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 862
    Points : 3 609
    Points
    3 609
    Par défaut
    Une fois ton update fait, la valeur nouvelle valeur de PAC sera différente de l'ancienne (enfin normalement..., sinon il est inutile de faire l'update).

    La clause where ramènera les 50000 lignes égales à p_old_pac. Les lignes ayant été updatées précédemment étant égales à p_new_pac ne sont pas ramenées.
    Un problème sans solution est un problème mal posé

    Merci de poser vos questions sur le forum, je ne réponds pas aux questions posées par MP.

  9. #9
    Futur Membre du Club
    Inscrit en
    Septembre 2006
    Messages
    8
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 8
    Points : 5
    Points
    5
    Par défaut
    ok mais ce que je ne comprends pas c'est qu'une fois mon update effectué et les 50 000 premiers enregistrement mis à jour, ma requete d'update s'arrette là puisque la clause rownum<50000 exclut les enregistrements restants, non ?
    A ce moment là ma boucle passe a l'itération suivante et change de table (la boucle ne passe qu'une seule fois sur chaque table) .
    Comment faire pour que l'update, arrivé a 50 000 enregistrements mis a jour fasse le commit et continu avec les 50 000 suivants sur la meme table, puis fasse le commit et poursuive encore avec les 50 000 suivants et ainsi de suite jusqu'a avoir parcouru toute la table ?
    Sinon j'ai peut etre rien compris, désolé dans ce cas

  10. #10
    Membre expert

    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Janvier 2004
    Messages
    2 862
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 862
    Points : 3 609
    Points
    3 609
    Par défaut
    Regarde :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        loop
           EXECUTE IMMEDIATE req;
           commit;    
        exit when sql%notfound;
        end loop;
    J'exécute la commande autant de fois qu'il y a des lignes à mettre à jour, c'est à dire tant qu'il y a des lignes avec PAC = p_old_pac. Et je le fais par "paquets" de 50 000 lignes.

    Exemple :
    Tu as 102000 lignes à mettre à jour avec p_old_pac = 1 et p_new_pac = 2 :

    => au premier passage : je mets à jour les 50000 premières lignes donc pour ces 50000 lignes, PAC prends la valeur 2.

    => au second passage, je n'ai plus que 520000 lignes dont PAC est égale à 1 (pour les 50000 autres PAC est désormais égal à 2). Parmi ces 520000 lignes, je prends les 50000 premières et je leur attribue pour la colonne PAC la valeur 2.

    => au troisième passage, je n'ai plus que 20000 lignes dont PAC est égal à 1 (pour les 100000 autres, PAC est désormais égal à 2). Je mets à jour pour ces 2000 lignes PAC à 2.

    => au quatrième passage : je n'ai plus de ligne à mettre à jour, je sors de ma boucle et je passe à la table suivante.

    C'est ce que tu voulais non ?
    Un problème sans solution est un problème mal posé

    Merci de poser vos questions sur le forum, je ne réponds pas aux questions posées par MP.

  11. #11
    Futur Membre du Club
    Inscrit en
    Septembre 2006
    Messages
    8
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 8
    Points : 5
    Points
    5
    Par défaut
    Merci Beaucoup PlaineR pour ta patience avec le débutant que je suis

    Je vais tester ça aujourd'hui et je mettrai la balise "Résolu" dès que ce sera validé (mais je n'ai aucun doute la dessus) .
    Je connaissais pas sql%notfound, décidément le pl/sql est plein de ressources

    Encore Merci

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

Discussions similaires

  1. Réponses: 5
    Dernier message: 18/12/2012, 08h24
  2. Réponses: 2
    Dernier message: 07/02/2011, 20h16
  3. comment faire pour supprimer tous les enregistrements d'une table
    Par sehing7 dans le forum VB 6 et antérieur
    Réponses: 1
    Dernier message: 14/04/2009, 14h13
  4. Comment faire un commit toutes les 10.000 transactions ?
    Par Invité dans le forum Administration
    Réponses: 7
    Dernier message: 04/02/2008, 15h05
  5. Réponses: 4
    Dernier message: 29/03/2007, 19h39

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