Oracle
 sql >> Teknologi Basis Data >  >> RDS >> Oracle

cara mengambil, menghapus, komit dari kursor

Mengapa Anda ingin melakukan dalam batch? Itu hanya akan memperlambat pemrosesan Anda. Kecuali ada sesi lain yang mencoba memodifikasi baris yang Anda coba hapus, yang tampaknya bermasalah karena alasan lain, pendekatan yang paling efisien adalah dengan menghapus data dengan satu DELETE, yaitu

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

Tentu saja, mungkin ada cara yang lebih optimal untuk menulis ini tergantung pada bagaimana kueri di belakang kursor Anda dirancang.

Jika Anda benar-benar ingin menghilangkan BULK COLLECT (yang akan memperlambat proses secara substansial), Anda dapat menggunakan sintaks WHERE CURRENT OF untuk melakukan 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.

Namun, ketahuilah bahwa karena Anda harus mengunci baris (dengan klausa FOR UPDATE), Anda tidak dapat memasukkan komit ke dalam loop. Melakukan komit akan melepaskan kunci yang Anda minta dengan FOR UPDATE dan Anda akan mendapatkan ORA-01002:fetch out of sequence error

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

Anda mungkin tidak mendapatkan kesalahan runtime jika Anda menghapus penguncian dan menghindari sintaks WHERE CURRENT OF, menghapus data berdasarkan nilai yang Anda ambil dari kursor. Namun, ini masih melakukan pengambilan lintas komit yang merupakan praktik yang buruk dan secara radikal meningkatkan kemungkinan bahwa Anda akan, setidaknya sebentar-sebentar, mendapatkan kesalahan ORA-01555:snapshot terlalu lama. Ini juga akan sangat lambat dibandingkan dengan pernyataan SQL tunggal atau opsi 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.

Tentu saja, Anda juga harus memastikan bahwa proses Anda dapat dimulai ulang jika Anda memproses beberapa subset baris dan memiliki sejumlah komit sementara yang tidak diketahui sebelum proses mati. Jika DELETE cukup untuk menyebabkan baris tidak lagi dikembalikan dari kursor Anda, proses Anda mungkin sudah dapat dimulai ulang. Namun secara umum, itu menjadi masalah jika Anda mencoba memecah satu operasi menjadi beberapa transaksi.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bagaimana kueri ini dapat ditingkatkan?

  2. Cara Menemukan Nama Batasan di Oracle

  3. Kesalahan alat migrasi Worklight 6.2

  4. Bagaimana cara menampilkan semua hak istimewa dari pengguna di Oracle?

  5. Penggabungan Oracle CTE