Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Usuwanie rekordów z jednej tabeli połączonej z inną tabelą SQL

Nie musisz używać OUTER JOIN z wyjątkiem sprawdzenia ile rzędów będzie ew. nie zostać usunięte.

Przykład takiego zapytania patrz poniżej (używam wygenerowanych danych testowych podanych na końcu odpowiedzi)

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   

Ze swoim rozmiarem danych powinieneś użyć HASH JOIN z full table scan na obu stołach, aby uzyskać akceptowalną wydajność.

Istnieją zasadniczo dwie opcje, jak wykonać DELETE

Aktualny widok dołączania

Pamiętaj, że w tym przypadku Twój mały stolik musi mieć unikalny indeks na ID, VERSION (lub klucz podstawowy)

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

W przeciwieństwie do tabeli BIG nie powinna mieć takiego ograniczenia . Jest to ważne, ponieważ wyraźnie wskazuje, że DUŻA tabela jest jedyną tablicą zachowującą klucze w widoku łączenia.

Po prostu umieść sprzężenie w małym stole nie można powielać wierszy z dużego stołu ze względu na unikalne ograniczenie

Zobacz tutaj więcej informacji o aktualizowaniu widoków przyłączenia

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 powyżej usuwa wiersze z BIG tabeli, ponieważ jest to jedyna tabela zachowująca klucze (patrz dyskusja powyżej)

Ten DML prowadzi do HASH JOIN

Usuń za pomocą EXISTS

Jeśli Twoja mała tabela nie ma klucza podstawowego (tzn. może zawierać zduplikowane wiersze o tym samym ID and VERSION ) musisz zastąpić do rozwiązania zaproponowanego w innej odpowiedzi .

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

Żadne indeksy nie są wymagane i należy oczekiwać planu wykonania z HASH JOIN RIGHT SEMI , co oznacza, że ​​oba podejścia nie różnią się tak naprawdę.

Przykładowe dane do testu

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. Oracle:unikanie wartości NULL w to_date

  2. ostrzeżenie :funkcja utworzona z błędem kompilacji

  3. Jak wyprowadzić wynik Oracle SQL do pliku w systemie Windows?

  4. Usuń zapytanie generujące UncategorizedSQLException i problem z pamięcią ORACLE we frameworku SPRING

  5. Konwertuj kolumnę datetime na czas UTC