2011-10-14 13 views
7

Estoy eliminando una fila en una tabla que está en un sitio de una relación muchos a muchos. También me gustaría eliminar las filas relacionadas en el otro lado de esa relación.Eliminación de filas relacionadas en una relación de varios a varios

Por ejemplo, supongamos que tengo las siguientes tablas y quiero eliminar una fila de Cars. También me gustaría eliminar las filas relacionadas de Drivers y, por supuesto, las filas ya no son necesarias en CarDrivers.

Table Cars: 
CarID  int 
CarName nvarchar(100) 

Table Drivers: 
DriverID int 
DriverName nvarchar(100) 

Table CarDrivers: 
CarID  int 
Driver  int 

sé cómo unirse a las tablas anteriores en una consulta SELECT. Pero no veo cómo eliminar datos a través de la relación.

Nota: Ambos lados de la relación implementan eliminaciones en cascada. Por lo tanto, por ejemplo, al eliminar una fila de Cars se eliminarán las filas relacionadas en CarDrivers. Pero obviamente eso no se propaga a la tabla Drivers.

+0

posible duplicado de [¿Cómo elimino de varias tablas utilizando INNER JOIN en el servidor SQL] (http://stackoverflow.com/questions/783726/how-do-i-delete-from-multiple-tables-using- inner-join-in-sql-server) –

+1

@OMG Ponies: disgree, no es una eliminación encadenada porque los CarDrivers a los controladores serán un niño que elimine un padre. El padre puede tener otros hijos. Ver mi respuesta, por favor – gbn

+0

-1 para preguntas engañosas e incompletas con un mal ejemplo – gbn

Respuesta

5

Creo que el mejor enfoque sería que primero tuviera que eliminar los datos de la tabla relacionada. En otras palabras, si desea eliminar un automóvil y los controladores correspondientes que utilizan ese automóvil, primero deberá eliminar los conductores y luego el automóvil. La tabla de unión eliminará los registros correctos debido a ON CASCADE DELETE.

Prueba esto:

delete 
from Drivers 
where DriverID in 
(
    select d.DriverID 
    from Drivers d 
    inner join CarDrivers cd 
    on d.DriverID = cd.Driver 
    inner join Cars c 
    on c.CarID = cd.CarID 
    where c.CarID = 1 
) 

delete 
from Cars 
where CarID = 1 

Naturalmente, no es necesario para codificar el 1 allí, se puede usar cualquier cosa, incluyendo un parámetro si está utilizando este fragmento de código en un procedimiento almacenado.

0

Ponga eliminaciones en cascada en la tabla CarDrivers.

+0

Eso solo borrará los datos relacionados en la tabla CarDrivers. Creo que el OP también quiere eliminar los datos de tabla correspondientes que forman parte de la unión. En cuyo caso, las eliminaciones en cascada no satisfarán la necesidad. –

0

Si usted tiene acceso a la base de datos y tener permisos para modificar las tablas, me acaba de crear las claves externas y especificar onUpdate y oncascade como tan:

ALTER TABLE [dbo].[Drivers] WITH CHECK ADD CONSTRAINT [FK__Cars] FOREIGN KEY([CarID]) 
REFERENCES [dbo].[Car] ([CarID]) 
ON UPDATE CASCADE 
ON DELETE CASCADE 

ALTER TABLE [dbo].[CarDrivers] WITH CHECK ADD CONSTRAINT [FK_Drivers_Cars] FOREIGN KEY([CarID]) 
REFERENCES [dbo].[Car] ([CarID]) 
ON UPDATE CASCADE 
ON DELETE CASCADE 

La ventaja de este enfoque es que no lo hace necesita preocuparse por los registros huérfanos. En el momento en que elimina un registro de la tabla Car, todos los relacionados en las otras tablas se eliminan y actualizan automáticamente. Sus declaraciones SQL son más cortas, también.

1

Su solicitud no tiene sentido

conductores como entidades existe por separado de los coches. Los automóviles pueden ser conducidos por muchos conductores, los conductores pueden conducir muchos automóviles. Es por eso que tienes la tabla de muchos.

Tenga en cuenta que los "conductores pueden conducir muchos autos". Esto significa que si elimina la fila Controladores, debe eliminar otras filas en CarDrivers.

Si aún desea hacer esto, necesita un disparador en CarDrivers. El CASCADE de Controladores a CarDrivers eliminará otras filas de CarDrivers por usted. Tampoco puedo recordar el comportamiento predeterminado para la recursión activada.

¡Qué desastre!

Nota: este casi tiene sentido si usted tiene la singularidad de una de las columnas en la tabla de muchos a muchos, entonces debería ser una clave externa entre los coches y los conductores (único en el coche significa "a lo sumo un conductor por coche "significa NULL columna FK en automóviles)

+0

Las tablas Coche, Conductores y CarDrivers fueron solo un ejemplo para ilustrar lo que trato de hacer. Esto es lo que hace una aplicación con la que estoy trabajando. Revisaré el diseño de la manera que describió, pero puede que no sea mi decisión cambiar el diseño. Creo que tiene algo que ver con el hecho de que una de las tablas está vinculada a otras tablas y la tabla de conexiones contiene un par de campos adicionales. –

+0

@Jonathan Wood: el diseño es sensato si necesita una mesa de muchos. Es la solicitud que no es válida – gbn

+0

Mirándola más a fondo, parece que es una relación de uno a muchos; sin embargo, una tabla de unión se usa principalmente por las razones que describí. Puedo asegurarle que no tiene sentido dejar objetos huérfanos del otro lado de la relación. –

0

No hay relación entre los controladores y la tabla de automóviles. Esta relación es a través de la tabla CarDrivers. Por lo tanto, el problema todavía existe.

La única forma que conozco de automatizar la eliminación de CASCADE es eliminar el FK entre CarDrivers y la tabla Drivers y agregar un disparador de eliminación antes o después a CarDrivers para eliminar la entrada en los controladores donde el driver_id es el de la fila eliminado en CarDrivers.

Esto no está limpio de muchas maneras. Si la eliminación es realmente necesaria en la tabla de unión, entonces la relación probablemente esté modelada y una relación más clara habría sido modelar la relación simplemente como "hay muchos conductores de un automóvil" o un FK de automóviles en la tabla de controladores. . Como se señaló anteriormente, para la relación real de autos y conductores, una relación de muchos a muchos es en realidad correcta y nunca se eliminará un controlador solo porque el vehículo se haya totalizado o eliminado.

Cuestiones relacionadas