sql >> Databáze >  >> RDS >> Oracle

jak načíst, odstranit, odevzdat z kurzoru

Proč se chcete zavázat v dávkách? To jen zpomalí vaše zpracování. Pokud neexistují jiné relace, které se pokoušejí upravit řádky, které se pokoušíte odstranit, což se zdá problematické z jiných důvodů, nejúčinnějším přístupem by bylo jednoduše smazat data pomocí jediného DELETE, tj.

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

Samozřejmě může existovat optimálnější způsob zápisu v závislosti na tom, jak je navržen dotaz za kurzorem.

Pokud opravdu chcete odstranit BULK COLLECT (což proces podstatně zpomalí), můžete použít syntaxi WHERE CURRENT OF k provedení DELETE

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.

Uvědomte si však, že protože musíte zamknout řádek (klauzulí FOR UPDATE), nemůžete do smyčky vložit potvrzení. Provedení odevzdání by uvolnilo zámky, které jste požadovali pomocí FOR UPDATE, a dostanete chybu ORA-01002:fetch out of sequence

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

Pokud odstraníte zamykání a vyhnete se syntaxi WHERE CURRENT OF, smažete data na základě hodnot, které jste načetli z kurzoru, nemusí se zobrazit chyba za běhu. Stále však dochází k načítání přes commit, což je špatný postup a radikálně zvyšuje pravděpodobnost, že alespoň občas dostanete chybu ORA-01555:snímek je příliš starý. Bude to také bolestně pomalé ve srovnání s jedním příkazem SQL nebo možností 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.

Samozřejmě musíte také zajistit, aby byl váš proces restartovatelný v případě, že zpracováváte nějakou podmnožinu řádků a máte nějaký neznámý počet prozatímních potvrzení, než proces skončí. Pokud DELETE stačí k tomu, aby se řádek již nevracel z vašeho kurzoru, váš proces je pravděpodobně již restartovatelný. Ale obecně to znepokojuje, pokud se pokoušíte rozdělit jednu operaci na více transakcí.



  1. Zobrazení historie úloh SQL Server Agent pomocí Azure Data Studio

  2. Pochopení vstupního výstupního systému Hadoop

  3. Je možné mít dynamický cizí klíč a co je pro to nejlepší/správné?

  4. shell skript najít název souboru a počet řádků každého souboru, nyní vložte tento záznam do tabulky Oracle