Anzahl der von einem UPDATE in PL / SQL betroffenen Zeilen

162

Ich habe eine PL / SQL-Funktion (läuft unter Oracle 10g), in der ich einige Zeilen aktualisiere. Gibt es eine Möglichkeit herauszufinden, wie viele Zeilen vom UPDATE betroffen waren? Wenn ich die Abfrage manuell ausführe, wird mir mitgeteilt, wie viele Zeilen betroffen waren. Ich möchte diese Nummer in PL / SQL erhalten.

Thomas Lötzer
quelle

Antworten:

245

Sie verwenden die sql%rowcountVariable.

Sie müssen es direkt nach der Anweisung aufrufen, für die Sie die Anzahl der betroffenen Zeilen ermitteln müssen.

Beispielsweise:

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
quelle
4
Und die Zuweisung muss allen COMMITs vorausgehen
rshdev
@Clive Ich habe eine Prozedur mit INSERT INTO.. COMMITund auch in der gleichen Prozedur nach dem Einfügen, die ich habe UPDATE SET WHERE EXISTS..COMMIT, aber meine i := SQL%rowcount;gibt alle Zeilen anstelle der Zeilen zurück, die nur aktualisiert wurden. Was könnte sein?
Guilherme Matheus
26

Für diejenigen, die die Ergebnisse von einem einfachen Befehl erhalten möchten, könnte die Lösung sein:

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

Das Grundproblem besteht darin, dass SQL% ROWCOUNT eine PL / SQL-Variable (oder -Funktion) ist und nicht direkt über einen SQL-Befehl aufgerufen werden kann. Dies kann durch Verwendung eines PL / SQL-Blocks ohne Namen erreicht werden.

... Wenn jemand eine Lösung hat, um sie in einem SELECT-Befehl zu verwenden, wäre ich interessiert.

CLS
quelle
6

Alternativ können SQL%ROWCOUNT Sie dies innerhalb der Prozedur verwenden, ohne eine Variable deklarieren zu müssen

Ali H.
quelle
4
SQL% ROWCOUNT ist eine Funktion. Sie können sie nicht einfach "verwenden" - Sie müssen etwas damit tun - ob Sie sie in einer Variablen speichern oder als Eingabe an eine andere Prozedur senden oder zu einer anderen hinzufügen.
Jeffrey Kemp
8
Ich denke, der Punkt von Ali H ist, dass es nicht notwendig ist, es einer Variablen zuzuweisen, bis Sie eine andere SQL-Anweisung haben, die die Zeilenanzahl beeinflussen würde. Abgesehen davon stimme ich zu, dass es einer Variablen zugewiesen werden sollte, um zu vermeiden, dass später ein Fehler auftritt, falls jemand eine andere SQL-Anweisung hinzufügt, bevor sie aufgerufen wird. Und diese Antwort von Ali H sollte ein Kommentar zu Clives Antwort sein und nicht als separate Antwort veröffentlicht werden
Kirby,
1

SQL%ROWCOUNTkann auch ohne Zuweisung verwendet werden (zumindest ab Oracle 11g) ).

Solange im aktuellen Block keine Operation (Aktualisieren, Löschen oder Einfügen) ausgeführt wurde, SQL%ROWCOUNTwird diese auf null gesetzt. Dann bleibt es bei der Anzahl der Zeilen, die von der letzten DML-Operation betroffen sind:

Sagen wir, wir haben Tisch CLIENT

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

Wir würden es so testen:

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;

Ergebend:

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

Probieren Sie mal das hier an..


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;

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

Das Ergebnis ist wie folgt:


2 Client aktualisiert für 1
kein Client mit 2 val_cli.
Kein Client mit 3 val_cli.
1 Client aktualisiert für 4
kein Client mit 5 val_cli.
1 Client aktualisiert für 6
kein Client mit 7 val_cli.
Kein Client mit 8 val_cli.
Kein Client mit 9 val_cli.
1 Client für 10 aktualisiert
Anzahl der insgesamt betroffenen Zeilen Aktualisierungsvorgang: 5


Arun Sundriyal
quelle
Fügen Sie Ihrer Lösung Kommentare hinzu. Bitte seien Sie genau.
Kumar Abhishek
-3

Verwenden Sie die Analysefunktion Count (*) OVER PARTITION BY NULL. Dies zählt die Gesamtzahl der Zeilen

Gast
quelle
Wenn Sie nach dem Ausführen der Update-Anweisung überprüfen, wie viel Sie tatsächlich aktualisiert haben, gibt dies keine generische Lösung. Wenn meine Tabelle T beispielsweise eine Spalte c1 enthält, die "1" als Wert für alle enthält, und ich jetzt alle Zeilen für diese Spalte auf "2" aktualisiere, wie hilft die Partitionierung durch Null?
Nanosoft