web-dev-qa-db-fra.com

Comment supprimer toutes les contraintes de toutes les tables?

Je souhaite supprimer toutes les contraintes par défaut, vérifier les contraintes, les contraintes uniques, les clés primaires et les clés étrangères de toutes les tables d'une base de données SQL Server. Je sais comment obtenir tous les noms de contraintes à partir de sys.objects, mais comment remplir le ALTER TABLE partie?

30
Aaron Bertrand

Vous pouvez obtenir ces informations facilement en rejoignant sys.tables.object_id = sys.objects.parent_object_id pour ces types d'objets.

DECLARE @sql NVARCHAR(MAX);
SET @sql = N'';

SELECT @sql = @sql + N'
  ALTER TABLE ' + QUOTENAME(s.name) + N'.'
  + QUOTENAME(t.name) + N' DROP CONSTRAINT '
  + QUOTENAME(c.name) + ';'
FROM sys.objects AS c
INNER JOIN sys.tables AS t
ON c.parent_object_id = t.[object_id]
INNER JOIN sys.schemas AS s 
ON t.[schema_id] = s.[schema_id]
WHERE c.[type] IN ('D','C','F','PK','UQ')
ORDER BY c.[type];

PRINT @sql;
--EXEC sys.sp_executesql @sql;

PRINT est juste là pour le globe oculaire - si vous avez beaucoup de contraintes, il peut ne pas afficher tout le script car il est limité à 8K. Dans ces cas, consultez cette astuce pour d'autres façons de valider le script avant de l'exécuter.

Une fois que vous êtes satisfait du résultat, décommentez le EXEC.

38
Aaron Bertrand

J'ai commencé avec la réponse acceptée et modifié la structure pour utiliser une boucle while plutôt que pour construire l'instruction sql complète dans sql dynamique. J'aime mieux cela pour plusieurs raisons.

La requête n'est pas stockée dans la grande variable @sql. Cette implémentation permet une impression pour chaque contrainte supprimée à des fins de journalisation dans la sortie. L'exécution a semblé un peu plus rapide dans mes tests unitaires.

Set NoCount ON

Declare @schemaName varchar(200)
set @schemaName=''
Declare @constraintName varchar(200)
set @constraintName=''
Declare @tableName varchar(200)
set @tableName=''

While exists
(   
    SELECT c.name
    FROM sys.objects AS c
    INNER JOIN sys.tables AS t
    ON c.parent_object_id = t.[object_id]
    INNER JOIN sys.schemas AS s 
    ON t.[schema_id] = s.[schema_id]
    WHERE c.[type] IN ('D','C','F','PK','UQ')
    and t.[name] NOT IN ('__RefactorLog', 'sysdiagrams')
    and c.name > @constraintName
)

Begin   
    -- First get the Constraint
    SELECT 
        @constraintName=min(c.name)
    FROM sys.objects AS c
    INNER JOIN sys.tables AS t
    ON c.parent_object_id = t.[object_id]
    INNER JOIN sys.schemas AS s 
    ON t.[schema_id] = s.[schema_id]
    WHERE c.[type] IN ('D','C','F','PK','UQ')
    and t.[name] NOT IN ('__RefactorLog', 'sysdiagrams')
    and c.name > @constraintName

    -- Then select the Table and Schema associated to the current constraint
    SELECT 
        @tableName = t.name,
        @schemaName = s.name
    FROM sys.objects AS c
    INNER JOIN sys.tables AS t
    ON c.parent_object_id = t.[object_id]
    INNER JOIN sys.schemas AS s 
    ON t.[schema_id] = s.[schema_id]
    WHERE c.name = @constraintName

    -- Then Print to the output and drop the constraint
    Print 'Dropping constraint ' + @constraintName + '...'
    Exec('ALTER TABLE [' + @schemaName + N'].[' + @tableName + N'] DROP CONSTRAINT [' + @constraintName + ']')
End

Set NoCount OFF
6
yourbuddypal