Oracle
 sql >> Baza danych >  >> RDS >> Oracle

jak pobierać, usuwać, zatwierdzać z kursora

Dlaczego chcesz zatwierdzać partiami? To tylko spowolni twoje przetwarzanie. O ile nie istnieją inne sesje, które próbują zmodyfikować wiersze, które próbujesz usunąć, co wydaje się problematyczne z innych powodów, najskuteczniejszym podejściem byłoby po prostu usunięcie danych za pomocą jednego DELETE, tj.

DELETE FROM uiv_response_income uri
 WHERE EXISTS( 
    SELECT 1
      FROM (<<bulk_delete_dup query>>) bdd
     WHERE bdd.rowid = uri.rowid
  )

Oczywiście może istnieć bardziej optymalny sposób pisania tego, w zależności od tego, jak zaprojektowane jest zapytanie za kursorem.

Jeśli naprawdę chcesz wyeliminować BULK COLLECT (co znacznie spowolni proces), możesz użyć składni GDZIE BIEŻĄCY OF, aby wykonać USUŃ

SQL> create table foo
  2  as
  3  select level col1
  4    from dual
  5  connect by level < 10000;

Table created.

SQL> ed
Wrote file afiedt.buf

  1  declare
  2    cursor c1 is select * from foo for update;
  3    l_rowtype c1%rowtype;
  4  begin
  5    open c1;
  6    loop
  7      fetch c1 into l_rowtype;
  8      exit when c1%notfound;
  9      delete from foo where current of c1;
 10    end loop;
 11* end;
SQL> /

PL/SQL procedure successfully completed.

Pamiętaj jednak, że skoro musisz zablokować wiersz (za pomocą klauzuli FOR UPDATE), nie możesz umieścić zatwierdzenia w pętli. Wykonanie zatwierdzenia zwolni blokady, o które prosiłeś za pomocą opcji FOR UPDATE, a otrzymasz komunikat ORA-01002:błąd pobierania poza kolejnością

SQL> ed
Wrote file afiedt.buf

  1  declare
  2    cursor c1 is select * from foo for update;
  3    l_rowtype c1%rowtype;
  4  begin
  5    open c1;
  6    loop
  7      fetch c1 into l_rowtype;
  8      exit when c1%notfound;
  9      delete from foo where current of c1;
 10      commit;
 11    end loop;
 12* end;
SQL> /
declare
*
ERROR at line 1:
ORA-01002: fetch out of sequence
ORA-06512: at line 7

Możesz nie otrzymać błędu w czasie wykonywania, jeśli usuniesz blokadę i unikniesz składni WHERE CURRENT OF, usuwającej dane na podstawie wartości pobranych z kursora. Jednak nadal wykonuje to pobieranie przez zatwierdzenie, co jest kiepską praktyką i radykalnie zwiększa szanse, że przynajmniej sporadycznie otrzymasz błąd ORA-01555:migawka zbyt stara. Będzie również boleśnie powolny w porównaniu z pojedynczą instrukcją SQL lub opcją BULK COLLECT.

SQL> ed
Wrote file afiedt.buf

  1  declare
  2    cursor c1 is select * from foo;
  3    l_rowtype c1%rowtype;
  4  begin
  5    open c1;
  6    loop
  7      fetch c1 into l_rowtype;
  8      exit when c1%notfound;
  9      delete from foo where col1 = l_rowtype.col1;
 10      commit;
 11    end loop;
 12* end;
SQL> /

PL/SQL procedure successfully completed.

Oczywiście musisz również upewnić się, że proces jest możliwy do ponownego uruchomienia na wypadek, gdy przetwarzasz jakiś podzbiór wierszy i masz nieznaną liczbę tymczasowych zatwierdzeń przed śmiercią procesu. Jeśli DELETE wystarczy, aby wiersz nie był już zwracany z kursora, prawdopodobnie proces jest już możliwy do ponownego uruchomienia. Ale ogólnie jest to problem, jeśli spróbujesz podzielić jedną operację na wiele transakcji.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQLDeveloper nie wyświetla żadnych tabel pod połączeniami, gdzie jest napisane tabele

  2. Jak wstawić wiele wierszy do tej samej tabeli — Oracle 10g

  3. Łączenie się z bazą danych Oracle przez C#?

  4. Zadeklaruj dynamiczną tablicę w Oracle PL/SQL

  5. ORA-28040 Nie Pasujący protokół uwierzytelniania podczas łączenia z SQL PLUS do Oracle 12c DB przy użyciu klienta sql plus w wersji 11.1