Как мне удалить все ограничения из всех таблиц?

30

Я хочу удалить все ограничения по умолчанию, проверить ограничения, уникальные ограничения, первичные ключи и внешние ключи из всех таблиц в базе данных SQL Server. Я знаю, как получить все имена ограничений sys.objects, но как мне заполнить ALTER TABLEчасть?

Аарон Бертран
источник
Просто из любопытства, каков контекст такого запроса? Интересно, как адресуются функциональные зависимости (то есть индексированные представления, каскадные события на FK и UQ, для которых IGNORE_DUP_KEY = ON).
Соломон Руцкий
3
@srutzky Спросили о переполнении стека, но я решил создать более чистую, каноническую версию здесь. В любом случае это обычный запрос, часто часть более сложной задачи очистки базы данных (начало заново, очистка объектов, которые были ошибочно введены в master, и т. Д.). Я не вижу влияния на эти функциональные зависимости путем удаления ограничений - на самом деле я подозреваю, что в большинстве случаев более крупная картина также усекает или удаляет таблицы. Отбрасывание ограничений сначала позволяет это.
Аарон Бертран

Ответы:

36

Вы можете легко получить эту информацию, присоединившись sys.tables.object_id = sys.objects.parent_object_idк этим типам объектов.

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это просто для наглядности - если у вас много ограничений, он может не отображать весь скрипт, потому что он ограничен 8K. В этих случаях см. Этот совет для других способов проверки скрипта перед запуском.

Как только вы довольны результатом, раскомментируйте EXEC.

Аарон Бертран
источник
3
Возможно, вы также захотите убрать ограничения внешнего ключа перед первичными ключами; ORDER BY (CASE WHEN c.[type] IN ('PK', 'UQ') THEN 1 ELSE 0 END)
Даниэль Хутмахер
1
@ Хороший вопрос Дэниела, возможно, достаточно типа ORDER BY, пока SQL Server не введет новые типы ограничений.
Аарон Бертран
6

Я начал с принятого ответа и изменил структуру, чтобы использовать цикл while, а не создавать полный оператор SQL в динамическом SQL. Мне нравится это лучше по нескольким причинам.

Запрос не сохраняется в большой переменной @sql. Эта реализация допускает печать для каждого ограничения, которое отбрасывается для целей регистрации в выходных данных. Казалось, выполнение в моем модульном тестировании было немного быстрее.

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
yourbuddypal
источник