Numero di righe interessate da un AGGIORNAMENTO in PL / SQL


162

Ho una funzione PL / SQL (in esecuzione su Oracle 10g) in cui aggiorno alcune righe. C'è un modo per scoprire quante righe sono state interessate dall'aggiornamento? Quando eseguo la query manualmente mi dice quante righe sono state interessate, voglio ottenere quel numero in PL / SQL.

Risposte:


245

Si utilizza la sql%rowcountvariabile.

Devi chiamarlo subito dopo l'istruzione per la quale devi trovare il conteggio delle righe interessate.

Per esempio:

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
E l'incarico deve precedere qualsiasi COMMIT
rshdev

@Clive Ho una procedura con INSERT INTO.. COMMITe anche nella stessa procedura dopo l'inserimento, l'ho fatto UPDATE SET WHERE EXISTS..COMMIT, ma il mio i := SQL%rowcount;sta restituendo tutte le righe anziché solo quelle che sono state aggiornate. Cosa potrebbe essere?
Guilherme Matheus,

26

Per coloro che desiderano i risultati da un semplice comando, la soluzione potrebbe essere:

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

Il problema di base è che SQL% ROWCOUNT è una variabile (o funzione) PL / SQL e non è possibile accedervi direttamente da un comando SQL. Utilizzando un blocco PL / SQL noname, questo può essere ottenuto.

... Se qualcuno ha una soluzione per usarlo in un comando SELECT, sarei interessato.


6

in alternativa, SQL%ROWCOUNT è possibile utilizzarlo all'interno della procedura senza che sia necessario dichiarare una variabile


4
SQL% ROWCOUNT è una funzione, non puoi semplicemente "usarla" - devi fare qualcosa con essa - sia archiviandola in una variabile, sia inviandola come input a un'altra procedura o aggiungendola a qualcos'altro.
Jeffrey Kemp,

8
Penso che il punto di Ali H sia che non è necessario assegnarlo a una variabile fino a quando non si dispone di un'altra istruzione SQL che influirebbe sul conteggio delle righe. Detto questo, sono d'accordo che dovrebbe essere assegnato a una variabile per evitare di causare un bug in seguito se qualcuno dovesse aggiungere un'altra istruzione SQL prima che venga chiamata. E, questa risposta di Ali H dovrebbe essere un commento sulla risposta di Clive piuttosto che pubblicata come una risposta separata
Kirby,

1

SQL%ROWCOUNTpuò anche essere usato senza essere assegnato (almeno da Oracle 11g ).

Finché non è stata eseguita alcuna operazione (aggiornamenti, eliminazioni o inserimenti) all'interno del blocco corrente, SQL%ROWCOUNTè impostato su null. Quindi rimane con il numero di riga interessato dall'ultima operazione DML:

diciamo che abbiamo un CLIENTE da tavolo

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

Lo testeremmo in questo modo:

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;

Con il risultato di:

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

Provi questo, per favore..


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;

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

Il risultato sarà come di seguito:


2 client aggiornati per 1
nessun client con 2 val_cli.
nessun client con 3 val_cli.
1 client aggiornato per 4
nessun client con 5 val_cli.
1 client aggiornato per 6
nessun client con 7 val_cli.
nessun client con 8 val_cli.
nessun client con 9 val_cli.
1 client aggiornato per 10
Numero di righe totali interessate dall'operazione di aggiornamento: 5



Aggiungi commenti alla tua soluzione, si prega di essere specifici.
Kumar Abhishek, il

-3

Utilizzare la funzione analitica Count (*) OVER PARTITION BY NULL Questo conterà il numero totale di righe


Dopo aver eseguito la dichiarazione di aggiornamento se controlli il conteggio su ciò che hai effettivamente aggiornato - Questo non fornisce alcuna soluzione generica. Ad esempio, se la mia tabella T ha una colonna c1 che contiene "1" come valore per tutti e ora aggiorno tutte le righe per quella colonna a "2", come sarà il partizionamento per null?
nanosoft,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.