web-dev-qa-db-fra.com

Désactiver la contrainte de clé étrangère, vous ne pouvez toujours pas tronquer la table? (SQL Server 2005)

J'ai une table appelée PX_Child qui a une clé étrangère sur PX_Parent. Je voudrais désactiver temporairement cette contrainte FK afin de pouvoir tronquer PX_Parent. Je ne sais pas comment cela se passe cependant.

J'ai essayé ces commandes

ALTER TABLE PX_Child NOCHECK CONSTRAINT ALL

ALTER TABLE PX_Parent NOCHECK CONSTRAINT ALL

(truncate commands)

ALTER TABLE PX_Child CHECK CONSTRAINT ALL

ALTER TABLE PX_Parent CHECK CONSTRAINT ALL

Mais le tronqué me dit toujours qu'il ne peut pas tronquer PX_Parent à cause d'une contrainte de clé étrangère. J'ai regardé tout autour du net et n'arrive pas à trouver ce que je fais mal, désolé pour la nature fondamentale de cette question.

27
larryq

Vous ne pouvez pas tronquer la table s'il existe une clé étrangère la référençant, y compris des contraintes désactivées. Vous devez supprimer les contraintes de clé étrangère ou utiliser la commande DELETE.

39
bobs

Il existe un moyen plus simple. J'ai été confronté au même problème et j'ai trouvé cette solution: https://www.mssqltips.com/sqlservertip/3347/drop-and-recreate-all-foreign-key-constraints-in-sql-server/

Si vous exécutez simplement cette requête dans votre base de données, elle générera le T-SQL que vous devez inclure avant/après votre sproc, afin de supprimer puis de restaurer toutes les contraintes de clé étrangère.

Ne vous inquiétez pas d'essayer de comprendre cette requête elle-même.

CREATE TABLE #x -- feel free to use a permanent table
(
  drop_script NVARCHAR(MAX),
  create_script NVARCHAR(MAX)
);

DECLARE @drop   NVARCHAR(MAX) = N'',
        @create NVARCHAR(MAX) = N'';

-- drop is easy, just build a simple concatenated list from sys.foreign_keys:
SELECT @drop += N'
ALTER TABLE ' + QUOTENAME(cs.name) + '.' + QUOTENAME(ct.name) 
    + ' DROP CONSTRAINT ' + QUOTENAME(fk.name) + ';'
FROM sys.foreign_keys AS fk
INNER JOIN sys.tables AS ct
  ON fk.parent_object_id = ct.[object_id]
INNER JOIN sys.schemas AS cs 
  ON ct.[schema_id] = cs.[schema_id];

INSERT #x(drop_script) SELECT @drop;

-- create is a little more complex. We need to generate the list of 
-- columns on both sides of the constraint, even though in most cases
-- there is only one column.
SELECT @create += N'
ALTER TABLE ' 
   + QUOTENAME(cs.name) + '.' + QUOTENAME(ct.name) 
   + ' ADD CONSTRAINT ' + QUOTENAME(fk.name) 
   + ' FOREIGN KEY (' + STUFF((SELECT ',' + QUOTENAME(c.name)
   -- get all the columns in the constraint table
    FROM sys.columns AS c 
    INNER JOIN sys.foreign_key_columns AS fkc 
    ON fkc.parent_column_id = c.column_id
    AND fkc.parent_object_id = c.[object_id]
    WHERE fkc.constraint_object_id = fk.[object_id]
    ORDER BY fkc.constraint_column_id 
    FOR XML PATH(N''), TYPE).value(N'.[1]', N'nvarchar(max)'), 1, 1, N'')
  + ') REFERENCES ' + QUOTENAME(rs.name) + '.' + QUOTENAME(rt.name)
  + '(' + STUFF((SELECT ',' + QUOTENAME(c.name)
   -- get all the referenced columns
    FROM sys.columns AS c 
    INNER JOIN sys.foreign_key_columns AS fkc 
    ON fkc.referenced_column_id = c.column_id
    AND fkc.referenced_object_id = c.[object_id]
    WHERE fkc.constraint_object_id = fk.[object_id]
    ORDER BY fkc.constraint_column_id 
    FOR XML PATH(N''), TYPE).value(N'.[1]', N'nvarchar(max)'), 1, 1, N'') + ');'
FROM sys.foreign_keys AS fk
INNER JOIN sys.tables AS rt -- referenced table
  ON fk.referenced_object_id = rt.[object_id]
INNER JOIN sys.schemas AS rs 
  ON rt.[schema_id] = rs.[schema_id]
INNER JOIN sys.tables AS ct -- constraint table
  ON fk.parent_object_id = ct.[object_id]
INNER JOIN sys.schemas AS cs 
  ON ct.[schema_id] = cs.[schema_id]
WHERE rt.is_ms_shipped = 0 AND ct.is_ms_shipped = 0;

UPDATE #x SET create_script = @create;

PRINT @drop;
PRINT @create;

/*
EXEC sp_executesql @drop
-- clear out data etc. here
EXEC sp_executesql @create;
*/

Génère un tas de:

ALTER TABLE [dbo].[Whatever] DROP CONSTRAINT....
--
ALTER TABLE [dbo].[Whatever] ADD CONSTRAINT....
14
RJB

Le serveur SQL ne vous permettra pas de tronquer la table tant que la contrainte existe, même si elle est désactivée. Supprimez la contrainte et recréez-la après avoir tronqué la table. Ou simplement déposez et recréez les tables, selon ce qui est plus facile à faire dans votre application.

5
Paul Groke

Il n'y a pas une telle option pour tronquer la table alors que la contrainte de clé étrangère mais nous pouvons utiliser une astuce comme

 ALTER TABLE [dbo].[table2] DROP CONSTRAINT [FK_table2_table1]
    GO
    truncate table [table1]
GO
    ALTER TABLE [dbo].[table2]  WITH CHECK ADD  CONSTRAINT [FK_table2_table1] FOREIGN KEY([FKId])
    REFERENCES [dbo].[table1] ([ID])
    GO

    ALTER TABLE [dbo].[table2] CHECK CONSTRAINT [FK_table2_table1]
    GO
1
Bhargil Joshi