Liczba wierszy objętych UPDATE w PL / SQL

162

Mam funkcję PL / SQL (działającą na Oracle 10g), w której aktualizuję niektóre wiersze. Czy istnieje sposób, aby dowiedzieć się, na ile wierszy wpłynęła aktualizacja? Podczas ręcznego wykonywania zapytania informuje mnie, ile wierszy zostało dotkniętych, chcę uzyskać tę liczbę w PL / SQL.

Thomas Lötzer
źródło

Odpowiedzi:

245

Używasz sql%rowcountzmiennej.

Musisz wywołać to bezpośrednio po instrukcji, dla której chcesz znaleźć liczbę wierszy, których dotyczy problem.

Na przykład:

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
źródło
4
Przypisanie musi poprzedzać jakiekolwiek COMMIT
rshdev
@Clive Mam procedurę z INSERT INTO... COMMITa także w tej samej procedurze po wstawieniu UPDATE SET WHERE EXISTS..COMMIT, ale moja i := SQL%rowcount;zwraca wszystkie wiersze zamiast tylko zaktualizowanych wierszy. Co może być?
Guilherme Matheus
26

Dla tych, którzy chcą wyników z prostego polecenia, rozwiązaniem może być:

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

Podstawowym problemem jest to, że SQL% ROWCOUNT jest zmienną (lub funkcją) PL / SQL i nie można uzyskać do niej bezpośredniego dostępu z polecenia SQL. Można to osiągnąć używając bloku noname PL / SQL.

... Jeśli ktoś ma rozwiązanie, aby użyć go w poleceniu SELECT, byłbym zainteresowany.

CLS
źródło
6

alternatywnie SQL%ROWCOUNT możesz użyć tego w procedurze bez konieczności deklarowania zmiennej

Ali H.
źródło
4
SQL% ROWCOUNT to funkcja, której nie można po prostu „użyć” - trzeba coś z nią zrobić - czy to zapisać w zmiennej, czy wysłać ją jako dane wejściowe do innej procedury, czy też dodać do czegoś innego.
Jeffrey Kemp
8
Myślę, że celem Ali H jest to, że nie jest konieczne przypisywanie jej do zmiennej, dopóki nie pojawi się kolejna instrukcja SQL, która wpłynęłaby na liczbę wierszy. Biorąc to pod uwagę, zgadzam się, że należy go przypisać do zmiennej, aby uniknąć późniejszego powodowania błędu, gdyby ktoś dodał kolejną instrukcję SQL przed jej wywołaniem. I ta odpowiedź od Ali H powinna być komentarzem do odpowiedzi Clive'a, a nie opublikowana jako osobna odpowiedź
Kirby,
1

SQL%ROWCOUNTmoże być również używany bez przypisania (przynajmniej z Oracle 11g ).

Dopóki żadna operacja (aktualizacje, usuwanie lub wstawianie) nie została wykonana w bieżącym bloku, SQL%ROWCOUNTma wartość null. Następnie pozostaje z liczbą linii, na które wpłynęła ostatnia operacja DML:

powiedz, że mamy tabeli KLIENTA

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

Testowalibyśmy to w ten sposób:

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;

Wynik:

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
źródło
-1

Spróbuj tego…


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;

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

Wynik będzie taki jak poniżej:


2 klient zaktualizowany dla 1
brak klienta z 2 val_cli.
brak klienta z 3 val_cli.
1 klient zaktualizowany dla 4
bez klienta z 5 val_cli.
1 klient zaktualizowany dla 6
bez klienta z 7 val_cli.
brak klienta z 8 val_cli.
brak klienta z 9 val_cli.
1 klient zaktualizowany dla 10
Liczba wszystkich linii, których dotyczy operacja aktualizacji: 5


Arun Sundriyal
źródło
Dodaj komentarze do swojego rozwiązania. Podaj konkretne.
Kumar Abhishek
-3

Użyj funkcji analitycznej Count (*) OVER PARTITION BY NULL Spowoduje to policzenie łącznej liczby wierszy

Gość
źródło
Po uruchomieniu instrukcji aktualizacji, jeśli sprawdzisz liczbę faktycznych aktualizacji - nie daje to żadnego ogólnego rozwiązania. Na przykład, jeśli moja tabela T ma jedną kolumnę c1, która zawiera „1” jako wartość dla wszystkich, a teraz zaktualizuję wszystkie wiersze dla tej kolumny do „2”, w jaki sposób podział na partycje przez pomoc zerową?
nanosoft