Як видалити всі обмеження з усіх таблиць?


30

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


Щойно з цікавості, який контекст такого запиту? Цікаво, як вирішуються функціональні залежності (тобто індексовані види, події каскаду на FK та UQ, які мали IGNORE_DUP_KEY = ON).
Соломон Руцький

3
@srutzky Це було запитано в Stack Overflow, але я вирішив створити тут більш чисту, канонічну версію. У будь-якому випадку це звичайний запит, часто це частина більшого завдання очищення бази даних (починаючи заново, очищаючи об'єкти, помилково введені в майстер тощо). Я не бачу, щоб ці функціональні залежності впливали, скидаючи обмеження - адже я підозрюю, що в більшості випадків більша картина також обрізається або скидає таблиці. Скасування обмежень спочатку дозволяє це.
Аарон Бертран

Відповіді:


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
@ Даніель хороший момент, тип ЗАМОВЛЕННЯ, ймовірно, достатній, поки 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.