sql >> Database >  >> RDS >> Oracle

Records verwijderen uit de ene tabel die is samengevoegd met een andere tabel SQL

U hoeft OUTER JOIN niet te gebruiken behalve de controle hoeveel rijen resp. zal niet worden verwijderd.

Een voorbeeld van zo'n vraag zie hieronder (ik gebruik gegenereerde testgegevens aan het einde van het antwoord)

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   

Met uw gegevensgrootte moet u een HASH JOIN . gebruiken met full table scan op beide tafels om acceptabele prestaties te krijgen.

Er zijn in principe twee opties om de DELETE . te doen

Bijwerkbare deelnameweergave

Merk op dat in dit geval uw kleine tabel een unieke index moet hebben op ID, VERSION (of een primaire sleutel)

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

In tegenstelling tot de BIG-tabel zou een dergelijke beperking niet moeten hebben . Dit is belangrijk, omdat het duidelijk aangeeft dat uw GROTE tabel de enige tabel is die de sleutel behoudt in de weergave Samenvoegen.

Plaats eenvoudig een join in de kleine tabel kan geen rijen dupliceren van de grote tafel vanwege de unieke beperking

Zie hier meer informatie over Het bijwerken van een deelnameweergave

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
)

De delete hierboven verwijdert rijen uit de BIG tabel omdat dit de enige tabel is die de sleutel behoudt (zie de discussie hierboven)

Deze DML leidt tot een HASH JOIN

Verwijderen met EXISTS

Als uw kleine tabel geen primaire sleutel heeft (d.w.z. hij kan dubbele rijen bevatten met dezelfde ID and VERSION ) je moet terugval naar de oplossing voorgesteld in ander antwoord .

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

Er zijn geen indexen vereist en u mag een uitvoeringsplan verwachten met HASH JOIN RIGHT SEMI , wat betekent dat beide benaderingen niet echt verschillend zijn.

Voorbeeldgegevens voor test

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. Spotlight Tuning Pack Basic:de beste gratis SQL-optimalisatietool

  2. java.sql.SQLException Parameterindex buiten bereik (1> aantal parameters, dat is 0)

  3. Verschil tussen codering en sortering?

  4. MySQL Great Circle Distance (Haversine-formule)