Número de linhas afetadas por uma UPDATE no PL / SQL

162

Eu tenho uma função PL / SQL (em execução no Oracle 10g) na qual atualizo algumas linhas. Existe uma maneira de descobrir quantas linhas foram afetadas pelo UPDATE? Ao executar a consulta manualmente, ele informa quantas linhas foram afetadas, desejo obter esse número no PL / SQL.

Thomas Lötzer
fonte

Respostas:

245

Você usa a sql%rowcountvariável

É necessário chamá-lo logo após a instrução para a qual você precisa encontrar a contagem de linhas afetadas.

Por exemplo:

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
fonte
4
E atribuição deve preceder nenhum commit
rshdev
@Clive Eu tenho um procedimento com INSERT INTO.. COMMITe também no mesmo procedimento após a inserção, tenho UPDATE SET WHERE EXISTS..COMMIT, mas o meu i := SQL%rowcount;está retornando todas as linhas em vez das linhas que foram atualizadas apenas. O que poderia ser?
Guilherme Matheus
26

Para aqueles que desejam os resultados de um comando simples, a solução pode ser:

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

O problema básico é que o SQL% ROWCOUNT é uma variável (ou função) PL / SQL e não pode ser acessado diretamente de um comando SQL. Usando um bloco PL / SQL que não seja o nome, isso pode ser alcançado.

... Se alguém tiver uma solução para usá-lo em um comando SELECT, eu estaria interessado.

CLS
fonte
6

Como alternativa, SQL%ROWCOUNT você pode usá-lo dentro do procedimento sem precisar declarar uma variável

Ali H
fonte
4
SQL% ROWCOUNT é uma função, você não pode simplesmente "usá-la" - você precisa fazer algo com ela - seja armazenando em uma variável ou enviando-a como entrada para outro procedimento ou adicionando-a a outra coisa.
9118 Jeffrey Kemp
8
Eu acho que o argumento de Ali H é que não é necessário atribuí-lo a uma variável até que você tenha outra instrução SQL que afetaria a contagem de linhas. Dito isto, concordo que ele deve ser atribuído a uma variável para evitar causar um erro posteriormente, caso alguém adicione outra instrução SQL antes de ser chamada. E, esta resposta de Ali H deve ser um comentário sobre a resposta de Clive, em vez de ser postada como uma resposta separada
Kirby
1

SQL%ROWCOUNTtambém pode ser usado sem ser atribuído (pelo menos a partir do Oracle 11g ).

Desde que nenhuma operação (atualizações, exclusões ou inserções) tenha sido executada dentro do bloco atual, SQL%ROWCOUNTseja definida como nula. Em seguida, ele permanece com o número de linhas afetadas pela última operação DML:

diga que temos mesa CLIENT

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

Testaríamos assim:

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 em:

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
fonte
-1

Tente este, por favor..


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;

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

O resultado será como abaixo:


2 clientes atualizados para 1
nenhum cliente com 2 val_cli.
nenhum cliente com 3 val_cli.
1 cliente atualizado para 4
nenhum cliente com 5 val_cli.
1 cliente atualizado para 6
nenhum cliente com 7 val_cli.
nenhum cliente com 8 val_cli.
nenhum cliente com 9 val_cli.
1 cliente atualizado para 10
Número total de linhas afetadas operação de atualização: 5


Arun Sundriyal
fonte
Adicione comentários à sua solução. Seja específico.
Kumar Abhishek
-3

Use a função analítica Contagem (*) OVER PARTITION BY NULL Contará o número total de linhas

convidado
fonte
Após executar a instrução update, se você verificar a contagem do que realmente atualizou - isso não fornece nenhuma solução genérica. Por exemplo, se minha tabela T tem uma coluna c1 que contém "1" como valor para todos e agora atualizo todas as linhas dessa coluna para "2", como o particionamento por ajuda nula?
Nanosoft 20/03