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 :

Procédure d'update et rowid


Sujet :

PL/SQL Oracle

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre très actif

    Homme Profil pro
    Responsable projets techniques
    Inscrit en
    Février 2003
    Messages
    980
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Responsable projets techniques
    Secteur : Biens de consommation

    Informations forums :
    Inscription : Février 2003
    Messages : 980
    Par défaut Procédure d'update et rowid
    Hello tout le monde,

    Parfois, lorsque j'ai un update assez volumineux à faire, j'utilise un truc du style:

    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
    declare
       cursor cur
       is
          select key1, key2
            from my_table
           where key1 = 'toto';
     
       type my_record is record (
          key1    my_table.key1%type,
          key2    my_table.key2%type
       );
     
       type my_data is table of my_record
          index by binary_integer;
     
       my_key   my_data;
       number_rows number := 0;
    begin
       open my_cur;
     
       loop
          fetch my_cur
          bulk collect into my_key limit 20000;
     
          if my_key.count > 0
          then
             for my_row in 1 .. my_key.count loop
                update my_table
                   set data1 = data1+data2
                 where key1 = my_key (my_row).key1
                   and key2 = my_key (my_row).key2;
             commit;
             end loop;
          else
             exit;
          end if;
       end loop;
     
       close my_cur;
     
       commit;
    exception
       when others
       then
          if my_cur%isopen
          then
             close my_cur;
          end if;
    end;
    Pour faire simple, je fait un curseur sur les colonnes de ma clé primaire, et je parcours la table par lot de 20000 lignes de ce curseur.

    Et aujourd'hui, je me suis demandé pourquoi ne pas plutôt utiliser un rowid à la place... ça éviterait d'avoir une table de record, et ça serait peut-être plus simple ?

    Ma question est donc toute bête : est-ce que quelque chose m'empêcherait de faire le même genre de requête en utilisant le rowid à la place des 2 colonnes de ma clé ?

    Question subsidiaire (parce que sur certaines base, je n'ai visiblement pas de rowid): c'est apparu sur une version récente ce rowid ? Ou est-ce qu'il faut l'activer d'une manière ou d'une autre ?

    Merci d'avance

  2. #2
    Membre chevronné
    Profil pro
    Inscrit en
    Février 2010
    Messages
    412
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 412
    Par défaut Jacky-tunning dans la place
    Le mieux ce serait d'utiliser un FORALL

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
       LOOP FETCH MY_CUR BULK COLLECT INTO MY_KEY LIMIT 20000;
     
       IF     MY_KEY.COUNT > 0 THEN
       --         FOR my_row IN 1 .. my_key.count loop
       --            UPDATE my_table
       --               SET data1 = data1+data2
       --             WHERE key1 = my_key (my_row).key1
       --               AND key2 = my_key (my_row).key2;
       FORALL I IN MY_KEY.FIRST .. MY_KEY.LAST 
          UPDATE MY_TABLE SET DATA1 = DATA1 + DATA2 
          WHERE KEY1 = MY_KEY(I).KEY1 AND KEY2 = MY_KEY(I).KEY2;
       COMMIT;
       ELSE ....
    De cette maniere, au lieu de faire les mises-a-jour une par une, il fait des paquets de 20 000. Ca devrait aller plus vite.
    Bon par contre, c'etait pas la question.

  3. #3
    Membre Expert
    Inscrit en
    Août 2009
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 1 073
    Par défaut
    Citation Envoyé par Alek-C Voir le message
    Ma question est donc toute bête : est-ce que quelque chose m'empêcherait de faire le même genre de requête en utilisant le rowid à la place des 2 colonnes de ma clé ?
    J'imagine que l'exemple a été très simplifié, parce que là on pourrait faire l'update directement, sans passer par un curseur ...
    Sinon, pour utiliser le rowid, il faut être sûr qu'il n'y ait pas de gros mouvements sur ta table en même temps. Je ne suis pas sûr cependant que pour ce genre d'utilisation, il y ait un vrai gain.

  4. #4
    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
    Sinon un curseur select for update nowait et un update par current of
    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
    declare
    cursor cur
       IS
          SELECT key1, key2
            FROM my_table
           WHERE key1 = 'toto' FOR UPDATE NOWAIT;
    BEGIN
     for r IN cur
     loop
       ...
      UDPATE my_table
    set ..
    where current of cur;
     
    end loop;
    end;

  5. #5
    Membre très actif

    Homme Profil pro
    Responsable projets techniques
    Inscrit en
    Février 2003
    Messages
    980
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Responsable projets techniques
    Secteur : Biens de consommation

    Informations forums :
    Inscription : Février 2003
    Messages : 980
    Par défaut
    @Rams7s: bonne idée le FOR ALL, je connaissais pas

    @Rei Ichido: le but est de ne pas faire sauter les undo et les rollback segment quand on met à jour une très grosse volumétrie, donc non, ça n'est pas forcément simplifié, mais je ne connais pas d'autres méthodes permettant de faire un update massif "en douceur"... s'il y a mieux, je suis preneur !
    Par contre, pourquoi il faudrait être sûr qu'il n'y ait pas de gros mouvement ? Il n'est pas sensé bouger le rowid si ?

    Le but est plus de simplifier la procédure (pas besoin de créer un record, on peut adapter l'ensemble facilement à une autre table puisque le rowid est toujours fait pareil) que d'améliorer les perfs.

    Edit: @McM: pas mal aussi comme piste, faut que je creuse ce truc de FOR UPDATE ^^

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

    Informations forums :
    Inscription : Août 2008
    Messages : 2 953
    Par défaut
    Citation Envoyé par Alek-C Voir le message
    Il n'est pas sensé bouger le rowid si ?
    Dans la majorité des cas le rowid est fixe mais :
    row_movement_clause
    question about row movement and alter table shrink

    Et dans ton cas utilise FORALL (même si la vrai bonne réponse au problème est d'avoir un UNDO correctement designé).
    Et rajoute RAISE au WHEN OTHERS !

Discussions similaires

  1. Problème procédure stockée update
    Par hugo7 dans le forum ASP.NET
    Réponses: 3
    Dernier message: 21/01/2009, 18h57
  2. [SQL SERV 2K] Problème d'update enregistrement dans procédure
    Par Tankian dans le forum MS SQL Server
    Réponses: 1
    Dernier message: 08/06/2006, 09h42
  3. Update VBA et RowID
    Par Sparal dans le forum Access
    Réponses: 7
    Dernier message: 23/03/2006, 12h43
  4. Réponses: 4
    Dernier message: 12/12/2005, 17h25
  5. Update appelant une procédure stockées
    Par meufeu dans le forum MS SQL Server
    Réponses: 1
    Dernier message: 06/10/2005, 18h31

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