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

Menghapus catatan dari satu tabel bergabung ke tabel lain SQL

Anda tidak perlu menggunakan OUTER JOIN kecuali untuk memeriksa berapa banyak baris yang akan resp. akan tidak akan dihapus.

Contoh kueri tersebut lihat di bawah (saya menggunakan data pengujian yang dihasilkan yang disediakan di akhir jawaban)

with del as (
select delta.id, delta.version,
decode(big.id,null,0,1) is_deleted
from delta
left outer join big 
on delta.id = big.id and delta.version = big.version
)
select is_deleted, count(*) cnt, max(id||'.'||version) eg_id_vers
from del
group by is_deleted;

IS_DELETED        CNT  EG_ID_VERS                                                                   
---------- ---------- ----------
         1      20000 99995.0   
         0         20 100100.0   

Dengan ukuran data Anda, Anda harus menggunakan HASH JOIN dengan full table scan di kedua tabel untuk mendapatkan performa yang dapat diterima.

Pada dasarnya ada dua opsi cara melakukan DELETE

Tampilan Gabung yang Dapat Diperbarui

Perhatikan bahwa dalam hal ini meja kecil Anda harus memiliki indeks unik ID, VERSION (atau kunci utama)

create unique index delta_idx on delta(id,version);

Sebaliknya tabel BIG seharusnya tidak memiliki batasan seperti itu . Ini penting, karena dengan jelas menunjukkan bahwa tabel BESAR Anda adalah satu-satunya tabel penyimpanan kunci dalam tampilan bergabung.

Sederhana, gabungkan ke tabel kecil tidak dapat menduplikasi baris dari meja besar karena batasan unik

Lihat di sini informasi lebih lanjut tentang Memperbarui Tampilan Gabung

delete from 
(
select delta.id, delta.version, big.id big_id, big.version
from big 
join delta 
on delta.id = big.id and delta.version = big.version
)

delete di atas menghapus baris dari BIG tabel karena ini adalah satu-satunya tabel pengawet kunci (lihat pembahasan di atas)

DML ini mengarah ke HASH JOIN

Hapus dengan EXISTS

Jika tabel kecil Anda tidak memiliki kunci utama (yaitu dapat berisi baris duplikat dengan ID and VERSION yang sama ) Anda harus fallback ke solusi yang diusulkan di jawaban lain .

DELETE FROM big 
    WHERE EXISTS (SELECT null
                  FROM delta
                  WHERE delta.id = big.id and delta.version = big.version
                 ) 

Tidak diperlukan indeks dan Anda akan mengharapkan rencana eksekusi dengan HASH JOIN RIGHT SEMI , yang berarti bahwa kedua pendekatan tersebut tidak terlalu berbeda.

Contoh Data untuk Pengujian

create table big as
select 
trunc(rownum/10) id, mod(rownum,10) version,
lpad('x',10,'Y') pad
from dual connect by level <= 1000000;

/* the DELTA table has 50 times less rows,
allow some rows out of range of the BIG table - those rows will not be deleted **/
drop table delta;
create table delta as
select 
trunc(rownum*50/10) id, mod(rownum*50,10) version
from dual connect by level <= 1001000/50;

create unique index delta_idx on delta(id,version);


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Apakah kita perlu menentukan bukan nol untuk kunci utama? Oracle/SQL

  2. Mengapa memilih dari prosedur tersimpan tidak didukung dalam database relasional?

  3. org.hibernate.tool.schema.spi.CommandAcceptanceException:Tidak dapat menjalankan perintah

  4. Mereferensikan tipe yang ditentukan pengguna Oracle melalui DBLINK?

  5. Oracle PL/SQL:UTL_FILE.FCOPY Contoh