183 votes

Nombre de lignes affectées par un UPDATE en PL/SQL

J'ai une fonction PL/SQL (fonctionnant sous Oracle 10g) dans laquelle je mets à jour certaines lignes. Existe-t-il un moyen de savoir combien de lignes ont été affectées par la mise à jour ? Lorsque j'exécute la requête manuellement, elle me dit combien de lignes ont été affectées. Je veux obtenir ce nombre en PL/SQL.

284voto

Clive Points 1295

Vous utilisez le sql%rowcount variable.

Vous devez l'appeler directement après l'instruction pour laquelle vous devez trouver le nombre de lignes affectées.

Par exemple :

set serveroutput ON; 
DECLARE 
    i NUMBER; 
BEGIN 
    UPDATE employees 
    SET    status = 'fired' 
    WHERE  name LIKE '%Bloggs'; 
    i := SQL%rowcount; 
    --note that assignment has to precede COMMIT
    COMMIT; 
    dbms_output.Put_line(i); 
END;

4 votes

Et l'affectation doit précéder tout COMMIT.

0 votes

@Clive j'ai une procédure avec INSERT INTO .. COMMIT et aussi dans la même procédure après l'insertion, j'ai UPDATE SET WHERE EXISTS..COMMIT mais mon i := SQL%rowcount; renvoie toutes les lignes au lieu des lignes qui ont été mises à jour uniquement. Que se passe-t-il ?

32voto

R. Daumann Points 11

Pour ceux qui souhaitent obtenir les résultats d'une simple commande, la solution pourrait être la suivante :

begin
  DBMS_OUTPUT.PUT_LINE(TO_Char(SQL%ROWCOUNT)||' rows affected.');
end;

Le problème de base est que SQL%ROWCOUNT est une variable (ou une fonction) PL/SQL, et qu'on ne peut pas y accéder directement à partir d'une commande SQL. Il est possible d'y parvenir en utilisant un bloc PL/SQL non nominatif.

... Si quelqu'un a une solution pour l'utiliser dans une commande SELECT, je serais intéressé.

7voto

Ali H Points 93

Alternativement, SQL%ROWCOUNT vous pouvez l'utiliser dans la procédure sans avoir besoin de déclarer une variable

4 votes

SQL%ROWCOUNT est une fonction, vous ne pouvez pas simplement "l'utiliser" - vous devez faire quelque chose avec elle - qu'il s'agisse de la stocker dans une variable, de l'envoyer en entrée d'une autre procédure ou de l'ajouter à quelque chose d'autre.

10 votes

Je pense que le point de vue d'Ali H est qu'il n'est pas nécessaire de l'assigner à une variable jusqu'à ce que vous ayez une autre instruction SQL qui affecterait le nombre de lignes. Cela dit, je suis d'accord pour dire qu'il faut l'assigner à une variable pour éviter de causer un bug plus tard si quelqu'un ajoute une autre instruction SQL avant qu'elle ne soit appelée. Et, cette réponse d'Ali H devrait être un commentaire sur la réponse de Clive plutôt que d'être postée comme une réponse séparée.

1voto

J. Chomel Points 5832

SQL%ROWCOUNT peuvent également être utilisés sans être affectés (au moins à partir de Oracle 11g ).

Tant qu'aucune opération (mises à jour, suppressions ou insertions) n'a été effectuée dans le bloc actuel, SQL%ROWCOUNT est mis à zéro. Ensuite, il reste avec le nombre de ligne affecté par la dernière opération DML :

disons que nous avons la table CLIENT

create table client (
  val_cli integer
 ,status varchar2(10)
)
/

Nous le testerions de cette façon :

begin
  dbms_output.put_line('Value when entering the block:'||sql%rowcount);

  insert into client 
            select 1, 'void' from dual
  union all select 4, 'void' from dual
  union all select 1, 'void' from dual
  union all select 6, 'void' from dual
  union all select 10, 'void' from dual;  
  dbms_output.put_line('Number of lines affected by previous DML operation:'||sql%rowcount);

  for val in 1..10
    loop
      update client set status = 'updated' where val_cli = val;
      if sql%rowcount = 0 then
        dbms_output.put_line('no client with '||val||' val_cli.');
      elsif sql%rowcount = 1 then
        dbms_output.put_line(sql%rowcount||' client updated for '||val);
      else -- >1
        dbms_output.put_line(sql%rowcount||' clients updated for '||val);
      end if;
  end loop;  
end;

Résultant en :

Value when entering the block:
Number of lines affected by previous DML operation:5
2 clients updated for 1
no client with 2 val_cli.
no client with 3 val_cli.
1 client updated for 4
no client with 5 val_cli.
1 client updated for 6
no client with 7 val_cli.
no client with 8 val_cli.
no client with 9 val_cli.
1 client updated for 10

-1voto

Arun Sundriyal Points 9

S'il vous plaît, essayez celui-ci


create table client (
  val_cli integer
 ,status varchar2(10)
);

---------------------
begin
insert into client
select 1, 'void' from dual
union all
select 4, 'void' from dual
union all
select 1, 'void' from dual
union all
select 6, 'void' from dual
union all
select 10, 'void' from dual;
end;

---------------------
select * from client;

---------------------
declare
  counter integer := 0;
begin
  for val in 1..10
    loop
      update client set status = 'updated' where val_cli = val;
      if sql%rowcount = 0 then
        dbms_output.put_line('no client with '||val||' val_cli.');
      else
        dbms_output.put_line(sql%rowcount||' client updated for '||val);
        counter := counter + sql%rowcount;
      end if;
  end loop;
   dbms_output.put_line('Number of total lines affected update operation: '||counter);
end;

---------------------
select * from client;

--------------------------------------------------------

Le résultat sera comme ci-dessous :


2 clients mis à jour pour 1
aucun client avec 2 val_cli.
aucun client avec 3 val_cli.
1 client mis à jour pour 4
aucun client avec 5 val_cli.
1 client mis à jour pour 6
aucun client avec 7 val_cli.
aucun client avec 8 val_cli.
aucun client avec 9 val_cli.
1 client mis à jour pour 10
Nombre de lignes totales affectées par l'opération de mise à jour : 5


0 votes

Ajoutez des commentaires à votre solution. Veuillez être précis.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X