2011-06-22 796 views
10

Tengo una tabla con muchas entradas de historial que contienen ID de cliente.¿Manera elegante de eliminar filas huérfanas?

Hay una tabla de clientes separada. Ocasionalmente, se eliminan algunas de las entradas de los clientes.

¿Hay alguna manera fácil, sin recorrer cada entrada del historial, de eliminar todas las filas de la tabla del historial donde la ID del cliente ya no existe porque la fila del cliente se eliminó?

+0

¿Desea hacer la eliminación cada vez que se elimina un cliente, o solo periódicamente? –

Respuesta

25
delete from history_table where customer_id not in (select customer_id from customers) 

Quiso decir algo como esto?

+0

Su debilidad es que no puede manejar autocombinaciones (por ejemplo, parentid en la tabla). También puede ser más lento que la combinación adecuada ... pero que quizás sea insignificante en las tablas pequeñas. –

8
DELETE h.* FROM history h 
LEFT JOIN customer c ON h.customer_id = c.id 
WHERE c.id IS NULL 

Estoy escribiendo esto desde lo alto de mi cabeza, pero se puede tener la idea con suerte.

Delete syntax documentation

+0

Esta es la solución adecuada. –

5

¿Qué tal:

DELETE FROM history_table 
WHERE customer_id NOT IN (SELECT customer_id FROM customer); 
1
DELETE FROM CUSTOMER_HISTORY CH 
WHERE NOT EXIST (SELECT 1 FROM CUSTOMER C WHERE C.CUSTOMER_ID = CH.CUSTOMER_ID) 
4

Puede usar la conexión en cascada con llaves foráneas para lograr esto. En el siguiente ejemplo, cada vez que se borra una fila de A, o se modifica un A_ID en A, este cambio se reflejará automáticamente en la tabla B. Puede leer más en las claves externas in the MySql Documentation.

CREATE TABLE A(
    A_ID INT, 
    PRIMARY_KEY(A_ID) 
) TYPE=InnoDB; 

CREATE TABLE B(
    B_ID INT, 
    A_ID INT, 
    CONSTRAINT FK_B_A FOREIGN KEY REFERENCES A(A_ID) ON DELETE CASCADE ON UPDATE CASCADE, 
    PRIMARY_KEY(B_ID, A_ID) 
) TYPE=InnoDB; 
Cuestiones relacionadas