Oracle
 sql >> база данни >  >> RDS >> Oracle

как да извличам, изтривам, ангажирам от курсора

Защо искате да се ангажирате на партиди? Това само ще забави вашата обработка. Освен ако няма други сесии, които се опитват да променят редовете, които се опитвате да изтриете, което изглежда проблематично по други причини, най-ефективният подход би бил просто да изтриете данните с едно изтриване, т.е.

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

Разбира се, може да има по-оптимален начин за писане на това в зависимост от това как е проектирана заявката зад вашия курсор.

Ако наистина искате да премахнете BULK COLLECT (което значително ще забави процеса), можете да използвате WHERE CURRENT OF синтаксиса, за да направите 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.

Имайте предвид обаче, че тъй като трябва да заключите реда (с клаузата FOR UPDATE), не можете да поставите ангажимент в цикъла. Извършването на ангажимент ще освободи заключванията, които сте поискали с FOR UPDATE и ще получите ORA-01002:грешка при извличане на последователност

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

Може да не получите грешка по време на изпълнение, ако премахнете заключването и избегнете синтаксиса WHERE CURRENT OF, като изтриете данните въз основа на стойността(ите), които сте извлекли от курсора. Въпреки това, това все още прави извличане през ангажимент, което е лоша практика и радикално увеличава шансовете, че поне от време на време ще получите грешка ORA-01555:моментна снимка твърде стара. Освен това ще бъде болезнено бавен в сравнение с единичния SQL оператор или опцията 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.

Разбира се, вие също трябва да се уверите, че вашият процес може да се рестартира, в случай че обработвате някакво подмножество от редове и имате някакъв неизвестен брой междинни ангажименти, преди процесът да умре. Ако DELETE е достатъчно, за да накара реда да не се връща повече от вашия курсор, вашият процес вероятно вече може да се рестартира. Но като цяло това е проблем, ако се опитате да разделите една операция на множество транзакции.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Формулярите на Oracle 10g не се отварят в разработчика на формуляри на Windows7 Professional

  2. Подниз с помощта на Oracle Когато има множество съвпадения?

  3. Каква е разликата между маската за дата "yy" и "rr" на Oracle?

  4. Как да върна резултат от много изрази за избор като една персонализирана таблица

  5. Тъй като SQL Server няма пакети, какво правят програмистите, за да го заобиколят?