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.

Thomas Lötzer
la source

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; 
Clive
la source
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é.

CLS
la source
6

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

Ali H
la source
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
J. Chomel
la source
-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


Arun Sundriyal
la source
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

client
la source
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