Précédent   Forum des professionnels en informatique > Bases de données > Oracle > PL/SQL
PL/SQL Forum d'entraide sur le PL/SQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 19/07/2011, 14h08   #1
Membre Expert
 
Homme Alexis
Intégrateur d'Exploitation
Inscription : février 2003
Messages : 876
Détails du profil
Informations personnelles :
Nom : Homme Alexis
Âge : 32
Localisation : France

Informations professionnelles :
Activité : Intégrateur d'Exploitation
Secteur : Biens de consommation

Informations forums :
Inscription : février 2003
Messages : 876
Points : 1 619
Points : 1 619
Envoyer un message via ICQ à Alek-C Envoyer un message via Skype™ à Alek-C
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 :
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
Alek-C est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/07/2011, 15h19   #2
Membre expérimenté
 
François
Inscription : février 2010
Messages : 305
Détails du profil
Informations personnelles :
Nom : François

Informations forums :
Inscription : février 2010
Messages : 305
Points : 535
Points : 535
Par défaut Jacky-tunning dans la place

Le mieux ce serait d'utiliser un FORALL

Code :
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.
Rams7s est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 19/07/2011, 15h53   #3
Membre Expert
 
Inscription : août 2009
Messages : 779
Détails du profil
Informations forums :
Inscription : août 2009
Messages : 779
Points : 1 098
Points : 1 098
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.
Rei Ichido est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/07/2011, 16h05   #4
McM
Expert Confirmé Sénior
 
Inscription : juillet 2003
Messages : 3 437
Détails du profil
Informations forums :
Inscription : juillet 2003
Messages : 3 437
Points : 4 173
Points : 4 173
Sinon un curseur select for update nowait et un update par current of
Code :
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;
__________________
More Code : More Bugs. Less Code : Less Bugs
McM est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 19/07/2011, 16h11   #5
Membre Expert
 
Homme Alexis
Intégrateur d'Exploitation
Inscription : février 2003
Messages : 876
Détails du profil
Informations personnelles :
Nom : Homme Alexis
Âge : 32
Localisation : France

Informations professionnelles :
Activité : Intégrateur d'Exploitation
Secteur : Biens de consommation

Informations forums :
Inscription : février 2003
Messages : 876
Points : 1 619
Points : 1 619
Envoyer un message via ICQ à Alek-C Envoyer un message via Skype™ à Alek-C
@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 ^^
Alek-C est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/07/2011, 21h59   #6
Membre Expert
 
Inscription : août 2008
Messages : 1 271
Détails du profil
Informations forums :
Inscription : août 2008
Messages : 1 271
Points : 1 929
Points : 1 929
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 !
skuatamad est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 04h24.


 
 
 
 
Partenaires

Hébergement Web