Come posso eliminare tutti i vincoli da tutte le tabelle?


30

Voglio eliminare tutti i vincoli predefiniti, controllare i vincoli, i vincoli univoci, le chiavi primarie e le chiavi esterne da tutte le tabelle in un database di SQL Server. So come ottenere tutti i nomi dei vincoli sys.objects, ma come faccio a popolare la ALTER TABLEparte?


Solo per curiosità, qual è il contesto di tale richiesta? Mi chiedo come vengono affrontate le dipendenze funzionali (ad esempio viste indicizzate, eventi a cascata su FK e UQ che avevano IGNORE_DUP_KEY = ON).
Solomon Rutzky,

3
@srutzky Mi è stato chiesto su Stack Overflow ma ho deciso di creare una versione canonica più pulita qui. Comunque è una richiesta comune, spesso parte di un compito più ampio di ripulire un database (ricominciare, ripulire oggetti che sono stati erroneamente inseriti nel master, ecc.). Non vedo che queste dipendenze funzionali siano influenzate dall'abbandono dei vincoli - in effetti sospetto che nella maggior parte dei casi anche l'immagine più grande stia troncando o rilasciando i tavoli. Eliminare prima i vincoli lo consente.
Aaron Bertrand

Risposte:


36

È possibile ricavare facilmente queste informazioni unendo sys.tables.object_id = sys.objects.parent_object_idtali tipi di oggetti.

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è lì solo per il bulbo oculare - se hai molti vincoli, potrebbe non mostrare l'intero script perché è limitato a 8 KB. In questi casi, consulta questo suggerimento per altri modi per convalidare lo script prima di eseguirlo.

Quando sei soddisfatto dell'output, decommenta il file EXEC.


3
È inoltre possibile assicurarsi di eliminare i vincoli di chiave esterna prima delle chiavi primarie; ORDER BY (CASE WHEN c.[type] IN ('PK', 'UQ') THEN 1 ELSE 0 END)
Daniel Hutmacher,

1
@Daniel buon punto, il tipo ORDER BY è probabilmente sufficiente fino a quando SQL Server non introduce nuovi tipi di vincolo.
Aaron Bertrand

6

Ho iniziato con la risposta accettata e modificato la struttura per utilizzare un ciclo while anziché per creare l'intera istruzione sql in sql dinamico. Mi piace di più per diversi motivi.

La query non è memorizzata nella grande variabile @sql. Questa implementazione consente una stampa per ogni vincolo che viene eliminato per scopi di registrazione nell'output. L'esecuzione sembrava un po 'più veloce nei test delle mie unità.

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.