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


162

J'ai une fonction PL / SQL (fonctionnant sur 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? Lors de l'exécution manuelle de la requête, il me dit combien de lignes ont été affectées, je veux obtenir ce nombre en PL / SQL.

Réponses:


245

Vous utilisez la sql%rowcountvariable.

Vous devez l'appeler directement après l'instruction pour laquelle vous devez trouver le nombre de lignes concerné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
Et la cession doit précéder tout COMMIT
rshdev

@Clive J'ai une procédure avec INSERT INTO.. COMMITet 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 pourrait être?
Guilherme Matheus

26

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

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 fonction) PL / SQL et ne peut pas être directement accessible à partir d'une commande SQL. En utilisant un bloc PL / SQL non nom, cela peut être réalisé.

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


6

Sinon, SQL%ROWCOUNT vous pouvez utiliser cela dans la procédure sans qu'il soit nécessaire de déclarer une variable


4
SQL% ROWCOUNT est une fonction, vous ne pouvez pas simplement "l'utiliser" - vous devez faire quelque chose avec - que ce soit le stocker dans une variable, ou l'envoyer comme entrée à une autre procédure, ou l'ajouter à quelque chose d'autre.
Jeffrey Kemp

8
Je pense que le point d'Ali H est qu'il n'est pas nécessaire de l'attribuer à une variable jusqu'à ce que vous ayez une autre instruction SQL qui affecterait le nombre de lignes. Cela étant dit, je suis d'accord qu'il devrait être assigné à une variable pour éviter de causer un bogue plus tard si quelqu'un ajoutait 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 publiée en tant que réponse séparée
Kirby

1

SQL%ROWCOUNTpeut également être utilisé sans être affecté (au moins à partir d' Oracle 11g ).

Tant qu'aucune opération (mises à jour, suppressions ou insertions) n'a été effectuée dans le bloc actuel, SQL%ROWCOUNTest défini sur null. Ensuite, il reste avec le numéro de ligne affecté par la dernière opération DML:

disons que nous avons une 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

-1

S'il vous plaît, essayez celui-la..


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 client mis à jour pour 1
pas de client avec 2 val_cli.
pas de client avec 3 val_cli.
1 client mis à jour pour 4
pas de client avec 5 val_cli.
1 client mis à jour pour 6
pas de client avec 7 val_cli.
pas de client avec 8 val_cli.
pas de client avec 9 val_cli.
1 client mis à jour pendant 10
Nombre total de lignes affectées opération de mise à jour: 5



Ajoutez des commentaires à votre solution, veuillez être précis.
Kumar Abhishek

-3

Utilisez la fonction analytique Count (*) OVER PARTITION BY NULL Cela comptera le nombre total de lignes


Après avoir exécuté l'instruction de mise à jour si vous vérifiez le décompte de ce que vous avez réellement mis à jour - Cela ne donne aucune solution générique. Par exemple, si ma table T a une colonne c1 qui contient «1» comme valeur pour tous et que maintenant je mets à jour toutes les lignes de cette colonne en «2», comment le partitionnement par null aidera-t-il?
nanosoft
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.