Autorreference de restricciones de key externa y eliminación

¿Cuál es la forma recomendada de manejar las restricciones de las keys externas autorreferenceles en SQL-Server?

Modelo de tabla:

enter image description here

fiData reference a un logging anterior en tabData. Si fiData un logging referencedo por fiData , la database arroja una exception:

"La instrucción DELETE entró en conflicto con la restricción SAME TABLE REFERENCE" FK_tabDataPrev_tabDataNext ". El conflicto se produjo en la database" MyDataBase ", en la tabla" dbo.tabData ", en la columna" fiData ".

si Enforce Foreignkey Constraint está configurado en "Sí".

No es necesario que elimine en cascada los loggings a los que se hace reference, pero tendría que establecer fiData=NULL lugar al que se hace reference. Mi idea es establecer Enforce Foreignkey Constraint a "No" y crear un desencadenador de eliminación. ¿Es esto recomendable o hay mejores forms?

Gracias.

A diferencia de Andomar, me gustaría usar un disparador, pero no eliminaría la verificación de restricciones. Si lo implementa como un en instead of desencadenar, puede restablecer las otras filas a nulo antes de realizar la eliminación real:

 CREATE TRIGGER T_tabData_D on tabData instead of delete as set nocount on update tabData set fiData = null where fiData in (select idData from deleted) delete from tabData where idData in (select idData from deleted) 

Es breve, es sucinto, no sería necesario si SQL Server pudiese manejar cascadas de key foránea en la misma tabla (en otro RDBMS ', usted puede simplemente especificar ON DELETE SET NULL para la restricción de key externa, YMMV).

Los triggers agregan complejidad implícita. En una database con desencadenadores, no sabrá qué hace una instrucción SQL al observarla. En mi experiencia, los factores desencadenantes son una mala idea, sin excepciones.

En su ejemplo, establecer forzado restringido a "No" significa que puede agregar una ID inexistente. Y el optimizador de consultas será less efectivo porque no puede asumir que la key es válida.

Considere crear un procedimiento almacenado en su lugar:

 create procedure dbo.NukeTabData( @idData int) as begin transaction update tabData set fiData = null where fiData = @idData delete from tabData where idData = @idData commit transaction go 

Esto es muy tarde para responder.

Pero para alguien que está buscando como yo.

y quieres cascade

aquí hay una muy buena explicación

http://devio.wordpress.com/2008/05/23/recursive-delete-in-sql-server/

El problema Aunque puede definir una key externa con CASCADE DELETE en SQL Server, las eliminaciones en cascada recursivas no son compatibles (es decir, la eliminación en cascada en la misma tabla).

Si crea un desencadenador INSTEAD OF DELETE, este desencadenador solo se activa para la primera instrucción DELETE y no se activa para los loggings eliminados recursivamente de este desencadenador.

Este comportamiento está documentado en MSDN para SQL Server 2000 y SQL Server 2005.

La solución Supongamos que tiene una tabla definida así:

 CREATE TABLE MyTable ( OID INT, -- primary key OID_Parent INT, -- recursion ... other columns ) 

a continuación, el desencadenador de eliminación se ve así:

 CREATE TRIGGER del_MyTable ON MyTable INSTEAD OF DELETE AS CREATE TABLE #Table( OID INT ) INSERT INTO #Table (OID) SELECT OID FROM deleted DECLARE @c INT SET @c = 0 WHILE @c <> (SELECT COUNT(OID) FROM #Table) BEGIN SELECT @c = COUNT(OID) FROM #Table INSERT INTO #Table (OID) SELECT MyTable.OID FROM MyTable LEFT OUTER JOIN #Table ON MyTable.OID = #Table.OID WHERE MyTable.OID_Parent IN (SELECT OID FROM #Table) AND #Table.OID IS NULL END DELETE MyTable FROM MyTable INNER JOIN #Table ON MyTable.OID = #Table.OID GO 
Intereting Posts