sql >> Base de Datos >  >> RDS >> Oracle

Eliminar registros de una tabla unida a otra tabla SQL

No necesita usar OUTER JOIN excepto por el control de cuántas filas habrá resp. no ser eliminado.

Vea un ejemplo de dicha consulta a continuación (utilizo los datos de prueba generados que se proporcionan al final de la respuesta)

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   

Con el tamaño de sus datos, debe usar un HASH JOIN con full table scan en ambas tablas para obtener un rendimiento aceptable.

Básicamente, hay dos opciones para hacer DELETE

Vista de unión actualizable

Tenga en cuenta que, en este caso, su tabla pequeña debe tener un índice único ID, VERSION (o una clave principal)

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

Al contrario, la mesa GRANDE no debería tener tal restricción . Esto es importante, porque indica claramente que su GRAN mesa es la única mesa que preserva las claves en la vista de unión.

Simplemente coloque una combinación en la tabla pequeña no se pueden duplicar filas de la mesa grande debido a la contraste único

Consulte aquí más información sobre Actualización de vistas de unión

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
)

El delete arriba elimina filas del BIG porque esta es la única tabla que conserva claves (ver la discusión anterior)

Este DML conduce a un HASH JOIN

Eliminar con EXISTE

Si su tabla pequeña no tiene clave principal (es decir, puede contener filas duplicadas con el mismo ID and VERSION ) debe retroceder a la solución propuesta en otra respuesta .

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

No se requieren índices y debe esperar un plan de ejecución con HASH JOIN RIGHT SEMI , lo que significa que ambos enfoques no son realmente diferentes.

Datos de muestra para la prueba

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);