Oracle
 sql >> Base de données >  >> RDS >> Oracle

Suppression d'enregistrements d'une table jointe à une autre table SQL

Vous n'avez pas besoin d'utiliser OUTER JOIN à l'exception de la vérification du nombre de lignes resp. ne va pas être supprimé.

Un exemple d'une telle requête voir ci-dessous (j'utilise les données de test générées fournies à la fin de la réponse)

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   

Avec la taille de vos données, vous devez utiliser un HASH JOIN avec full table scan sur les deux tables pour obtenir des performances acceptables.

Il existe essentiellement deux options pour effectuer le DELETE

Vue de jointure pouvant être mise à jour

Notez que dans ce cas votre petite table doit avoir un index unique sur ID, VERSION (ou une clé primaire)

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

Au contraire, la table BIG ne devrait pas avoir une telle contrainte . Ceci est important, car cela indique clairement que votre table BIG est la seule table de préservation des clés dans la vue de jointure.

Simple mettre une jointure à la petite table ne peut pas dupliquer les lignes de la grande table en raison de la contrainte unique

Voir ici plus d'informations sur la mise à jour d'une vue de jointure

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
)

Le delete ci-dessus supprime les lignes du BIG car c'est la seule table de conservation des clés (voir la discussion ci-dessus)

Ce DML conduit à un HASH JOIN

Supprimer avec EXISTS

Si votre petite table n'a pas de clé primaire (c'est-à-dire qu'elle peut contenir des lignes dupliquées avec les mêmes ID and VERSION ) vous devez replier à la solution proposée dans autre réponse .

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

Aucun index n'est requis et vous devez vous attendre à un plan d'exécution avec HASH JOIN RIGHT SEMI , ce qui signifie que les deux approches ne sont pas vraiment différentes.

Exemple de données pour le 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);