Número de filas afectadas por una ACTUALIZACIÓN en PL / SQL

162

Tengo una función PL / SQL (que se ejecuta en Oracle 10g) en la que actualizo algunas filas. ¿Hay alguna manera de averiguar cuántas filas se vieron afectadas por la ACTUALIZACIÓN? Cuando ejecuto la consulta manualmente, me dice cuántas filas se vieron afectadas, quiero obtener ese número en PL / SQL.

Thomas Lötzer
fuente

Respuestas:

245

Usas la sql%rowcountvariable.

Debe llamarlo inmediatamente después de la declaración para la que necesita encontrar el recuento de filas afectadas.

Por ejemplo:

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
fuente
44
Y la asignación debe preceder a cualquier COMPROMISO
rshdev
@Clive Tengo un procedimiento con INSERT INTO... COMMITy también en el mismo procedimiento después de la inserción, tengo UPDATE SET WHERE EXISTS..COMMIT, pero mi i := SQL%rowcount;está devolviendo todas las filas en lugar de las filas que se actualizaron solo. ¿Que puede ser?
Guilherme Matheus
26

Para aquellos que desean los resultados de un comando simple, la solución podría ser:

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

El problema básico es que SQL% ROWCOUNT es una variable (o función) PL / SQL, y no se puede acceder directamente desde un comando SQL. Al usar un bloque PL / SQL que no sea un nombre, esto se puede lograr.

... Si alguien tiene una solución para usarlo en un comando SELECT, estaría interesado.

CLS
fuente
6

alternativamente, SQL%ROWCOUNT puede usar esto dentro del procedimiento sin necesidad de declarar una variable

Ali H
fuente
44
SQL% ROWCOUNT es una función, no puede simplemente "usarla", necesita hacer algo con ella, ya sea almacenando en una variable, o enviándola como entrada a otro procedimiento, o agregándola a otra cosa.
Jeffrey Kemp
8
Creo que el punto de Ali H es que no es necesario asignarlo a una variable hasta que tenga otra instrucción SQL que afecte el recuento de filas. Dicho esto, estoy de acuerdo en que debe asignarse a una variable para evitar causar un error más tarde si alguien agrega otra instrucción SQL antes de que se llame. Y, esta respuesta de Ali H debería ser un comentario sobre la respuesta de Clive en lugar de publicarse como una respuesta separada
Kirby
1

SQL%ROWCOUNTtambién se puede usar sin ser asignado (al menos desde Oracle 11g ).

Siempre que no se haya realizado ninguna operación (actualizaciones, eliminaciones o inserciones) dentro del bloque actual, SQL%ROWCOUNTse establece en nulo. Luego permanece con el número de línea afectada por la última operación DML:

decir que tenemos mesa CLIENTE

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

Lo probaríamos de esta manera:

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;

Resultando 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
fuente
-1

Por favor, pruebe este..


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;

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

El resultado será el siguiente:


2 clientes actualizados para 1
sin cliente con 2 val_cli.
sin cliente con 3 val_cli.
1 cliente actualizado para 4
sin cliente con 5 val_cli.
1 cliente actualizado para 6
sin cliente con 7 val_cli.
sin cliente con 8 val_cli.
sin cliente con 9 val_cli.
1 cliente actualizado para 10
Número de líneas totales afectadas operación de actualización: 5


Arun Sundriyal
fuente
Agregue comentarios a su solución. Sea específico.
Kumar Abhishek
-3

Use la función analítica Count (*) SOBRE PARTICIÓN POR NULO Esto contará el número total de filas

invitado
fuente
Después de ejecutar la declaración de actualización, si verifica el recuento de lo que realmente actualizó, esto no proporciona ninguna solución genérica. Por ejemplo, si mi tabla T tiene una columna c1 que contiene "1" como valor para todos y ahora actualizo todas las filas para esa columna a "2", ¿cómo ayudará la partición por nulo?
nanosoft