La declaración DELETE está en conflicto con la restricción REFERENCE

11

Estoy tratando de eliminar a todos los usuarios pero aparece el error:

Msg 547, Level 16, State 0, Line 1
The DELETE statement conflicted with the REFERENCE constraint "FK_M02ArticlePersons_M06Persons". The conflict occurred in database "workdemo.no", table "dbo.M02ArticlePersons", column 'M06PersonId'.
The statement has been terminated.

La consulta:

DELETE FROM [workdemo.no].[dbo].[M06Persons] 
WHERE ID > '13'
GO

Parece que necesito usar on delete cascade;pero estoy atascado.

Mago oscuro
fuente

Respuestas:

18

No necesita usar la cascada de eliminación. Alguien (el autor del diseño del esquema) se aseguró de que no pueda eliminar a una persona a la que todavía hace referencia un artículo. Tuvo éxito, solo intentabas hacer esto y fue bloqueado, felicitaciones al diseñador.

Ahora ve y habla con alguien que diseñó el esquema y conoce las restricciones y pregúntale cómo eliminar adecuadamente los registros que estás tratando de eliminar, en el orden correcto y tomando las precauciones adecuadas para mantener la base de datos coherente.

Remus Rusanu
fuente
9

Aquí tiene dos opciones reales, puede deshabilitar las restricciones en la tabla. Esto generalmente no es una gran idea, ya que puede terminar con una mala condición de datos si está jugando con datos relacionados con otras tablas, pero no conoce el alcance completo de su esquema y puede adaptarse a sus propósitos:

ALTER TABLE [workdemo.no].[dbo].[M06Persons] NOCHECK CONSTRAINT [FK_M02ArticlePersons_M06Persons]

Recuerde volver a activar la restricción después de la eliminación con

ALTER TABLE [workdemo.no].[dbo].[M06Persons] WITH CHECK CHECK CONSTRAINT [FK_M02ArticlePersons_M06Persons]

La segunda opción sería eliminar y volver a agregar la restricción con la opción ON DELETE CASCADE mediante:

ALTER TABLE [workdemo.no].[dbo].[M06Persons] DROP CONSTRAINT [FK_M02ArticlePersons_M06Persons]

ALTER TABLE [workdemo.no].[dbo].[M06Persons] WITH NOCHECK ADD CONSTRAINT [FK_M02ArticlePersons_M06Persons] FOREIGN KEY(M06PersonId)
REFERENCES <parent table here> (<parent column here>)
ON DELETE CASCADE

Según su nombre FK, parece que su tabla principal es M02ArticlePersons y la columna principal es M06Persons.

Si no creó este esquema, trate de considerar por qué las restricciones pueden estar presentes y comprenda que violarlas de esta manera puede tener efectos secundarios no deseados.

Ahrotahntee
fuente
2

La tabla dbo.M02ArticlePersons de la columna M06PersonId se referencia en otra tabla. Entonces, antes de eliminar la declaración, deshabilite estas relaciones e intente nuevamente

a continuación es para deshabilitar la clave externa

 ALTER TABLE dbo.M02ArticlePersons NOCHECK CONSTRAINT FK_M02ArticlePersons_M06Persons

DELETE FROM [workdemo.no].[dbo].[M06Persons] 
  WHERE ID > '13'
GO

y esto es para habilitarlo

ALTER TABLE dbo.M02ArticlePersons CHECK CONSTRAINT FK_M02ArticlePersons_M06Persons

Espero que esto funcione

Navin 431
fuente
2
sugerencia horrible NUNCA debe deshabilitar una restricción FK a menos que sea un dba senior (en cuyo caso no habría escrito la pregunta anterior). Esas restricciones existen para evitar que elimine los registros. Deshabilitarlos willy nilly le dará malos datos en su base de datos. Estás recomendando una peor práctica, no una buena.
HLGEM
1

También hay otra opción manual:

Puede ir a la tabla secundaria y eliminar las filas secundarias a las que hace referencia la clave primaria. Luego puede eliminar la fila principal. Esto es esencialmente lo que hace la eliminación en cascada. De esta manera, no tiene que soltar / recrear / alterar sus restricciones.

StanleyJohns
fuente
1

Este pequeño código ayudará a cualquier tabla de la que desee eliminar registros. También se ocupa de la integridad referencial ...

El siguiente código generará sentencias DELETE. Solo especifique el nombre_estable_esquema.

Declare @sql1 varchar(max)
      , @ptn1 varchar(200)
      , @ctn1 varchar(200)
      , @ptn2 varchar(200)
      , @ctn2 varchar(200)
--
SET @ptn1 = ''
--
SET @ctn1 = ''
--
SET @ptn2 = ''
--
SET @ctn2 = ''
--
SELECT @sql1 = case when (@ptn1 <> OBJECT_NAME (f.referenced_object_id)) then
                         COALESCE( @sql1 + char(10), '') + 'DELETE' + char(10) + ' ' + OBJECT_NAME (f.referenced_object_id) + ' FROM ' + OBJECT_NAME(f.parent_object_id) + ', '+OBJECT_NAME (f.referenced_object_id) + char(10) +' WHERE ' + OBJECT_NAME(f.parent_object_id) + '.' + COL_NAME(fc.parent_object_id, fc.parent_column_id) +'='+OBJECT_NAME (f.referenced_object_id)+'.'+COL_NAME(fc.referenced_object_id, fc.referenced_column_id)
                    else
                         @sql1 + ' AND ' + OBJECT_NAME(f.parent_object_id) + '.' + COL_NAME(fc.parent_object_id, fc.parent_column_id) +'='+OBJECT_NAME (f.referenced_object_id)+'.'+COL_NAME(fc.referenced_object_id, fc.referenced_column_id)
                    end + char(10)
     , @ptn1 = OBJECT_NAME (f.referenced_object_id)
     , @ptn2  = object_name(f.parent_object_id)
FROM   sys.foreign_keys AS f
       INNER JOIN
       sys.foreign_key_columns AS fc ON f.object_id = fc.constraint_object_id
WHERE  f.parent_object_id = OBJECT_ID('dbo.M06Persons'); -- CHANGE here schema.table_name
--
print  '--Table Depended on ' + @ptn2 + char(10) + @sql1
Kin Shah
fuente