2011-11-24 25 views
23

Voy a eliminar datos en una tabla de SQL Server (principal) que tiene una relación con otra tabla (secundaria).
Intenté la consulta básica Eliminar. Pero no está funcionando (y sé que no lo hará).Eliminar datos con clave externa en la tabla de SQL Server

DELETE FROM table WHERE ... 

Volvió siguiente error

La instrucción DELETE en conflicto con la restricción REFERENCIA ...

que necesita para mantener el esquema de la tabla. Sé que solo necesito agregar algunas palabras en la consulta, alguna vez he hecho esto antes, pero simplemente no podía recordarlo.

Respuesta

12

Si desea que la eliminación sea automática, debe cambiar su esquema para que la restricción de la clave externa sea ON DELETE CASCADE.

Para obtener más información, consulte el MSDN page on Cascading Referential Integrity Constraints.

ETA (después de la aclaración del cartel): Si no puede actualizar el esquema, primero debe ELIMINAR manualmente los registros secundarios afectados.

+0

ah. Me perdí para contar esa parte en mi publicación, tengo que hacerlo funcionar sin cambiar el esquema. es posible verdad? – Andha

+1

No, no es posible con alguna consulta mágica OPCIÓN o lo que sea. Necesitas hacer las eliminaciones manualmente. –

28

Puede deshabilitar y volver a habilitar las restricciones de clave externa antes y después de borrar:

alter table MyOtherTable nocheck constraint all 
delete from MyTable 
alter table MyOtherTable check constraint all 
+5

Si deshabilita y luego vuelve a habilitar las restricciones, ¿no volverá a habilitar la habilitación debido a las referencias 'extranjeras 'rotas? –

+0

No, solo verifica la restricción cuando escribe valores nuevos en un campo; no vuelve a examinar toda la tabla cuando devuelve el cheque. –

+3

Bien. Esto significa que todos los datos en la tabla secundaria permanecerán allí. Estoy a punto de eliminar 2k filas, y creo que será voluminoso si guardo los datos en la tabla secundaria. Creo que lo haré de forma manual. Thx de todos modos para las respuestas chicos. Mereces +1 :) – Andha

2

Por lo tanto, es necesario DELETE filas relacionadas de las tablas en conflicto o más lógicas para UPDATE su columna FOREIGN KEY hacer referencia a otra PRIMARY KEY es de la tabla padre.

Además, es posible que desee leer este artículo Don’t Delete – Just Don’t

26

Es necesario eliminar manualmente los niños. el <condition> es el mismo para ambas consultas.

DELETE FROM child 
FROM cTable AS child 
INNER JOIN table AS parent ON child.ParentId = parent.ParentId 
WHERE <condition>; 

DELETE FROM parent 
FROM table AS parent 
WHERE <condition>; 
+0

¿Pueden estos dos DELETE combinarse de forma que solo tenga que escribir la parte una vez? –

+1

No lo creo, así que @ThomasTempelmann. Si solo desea escribir la condición una vez, deberá activar las eliminaciones en cascada en lugar de tratar manualmente cada tabla. La respuesta de Alastair Maw aquí también hace referencia a esta opción. –

2

para eliminar datos de las tablas que tienen relación de parent_child, primero hay que eliminar los datos de la tabla secundaria mencionando join continuación, sólo tiene que borrar los datos de la tabla padre, se da el siguiente ejemplo:

DELETE ChildTable 
FROM ChildTable inner join ChildTable on PParentTable.ID=ChildTable.ParentTableID 
WHERE <WHERE CONDITION> 


DELETE ParentTable 
WHERE <WHERE CONDITION> 
+0

Esta es la mejor respuesta si no está eliminando en cascada. Los cursores se comportan de forma horrible y eliminar las restricciones para eliminar podría dejar filas huérfanas en otras tablas. – Corv1nus

5

aquí va a agregar la clave externa para la tabla "niño"

ALTER TABLE child 
ADD FOREIGN KEY (P_Id) 
REFERENCES parent(P_Id) 
ON DELETE CASCADE 
ON UPDATE CASCADE; 

Después de que si se hace una consulta de eliminación en la tabla "padre" como esto

DELETE FROM parent WHERE ..... 

ya que el niño tiene una referencia a los padres con DELETE CASCADE, las filas "niño" también lo hará ser eliminado! junto con el "padre".

1

guión utiles que puede eliminar todos los datos de todas las tablas de una base de datos, reemplazar tt contigo nombre DATABSE:

declare @tablename nvarchar(100) 
declare c1 cursor for 
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_CATALOG='tt' AND TABLE_TYPE='BASE TABLE' 

open c1 
fetch next from c1 into @tablename 

while @@FETCH_STATUS = 0 
    begin 
    print @t1 
     exec('alter table ' + @tablename + ' nocheck constraint all') 
     exec('delete from ' + @tablename) 
     exec ('alter table ' + @tablename + ' check constraint all') 
     fetch next from c1 into @tablename 
    end 
close c1 
DEALLOCATE c1 
Cuestiones relacionadas