Tüm kısıtlamaları tüm tablolardan nasıl kaldırırım?


30

Tüm varsayılan kısıtlamaları bırakmak, kısıtlamaları kontrol etmek, benzersiz kısıtlamalar, birincil anahtarlar ve yabancı anahtarları bir SQL Server veritabanındaki tüm tablolardan istiyorum. Tüm kısıtlama adlarını nereden alacağımı biliyorum sys.objects, ancak ALTER TABLEkısmı nasıl doldururum ?


Sadece meraktan, böyle bir isteğin içeriği nedir? İşlevsel bağımlılıkların nasıl ele alındığını merak ediyorum (yani indekslenmiş görünümler, FK'lerde kaskad olayları ve IGNORE_DUP_KEY = ON olan UQ'lar).
Solomon Rutzky,

3
@srutzky Stack Overflow ile ilgili sorular soruldu ancak burada daha temiz, kanonik bir sürüm oluşturmaya karar verdim. Her neyse, genellikle bir veritabanını temizleme görevinin bir parçası (genel olarak, yanlışlıkla master'a yerleştirilmiş nesnelerin temizlenmesi vb.) Ortak bir istektir. Bu işlevsel bağımlılıkların kısıtlamaları düşürmekten etkilendiğini görmüyorum - aslında çoğu zaman daha büyük resmin tabloları kısalttığından veya düşürdüğünden şüpheleniyorum. Önce kısıtlamaları bırakmak buna izin verir.
Aaron Bertrand

Yanıtlar:


36

Bu bilgileri sys.tables.object_id = sys.objects.parent_object_id, bu nesne türlerine katılarak kolayca elde edebilirsiniz .

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;

PRINTsadece göz küresi için var - eğer çok fazla kısıtlama varsa, tüm senaryoyu göstermeyebilir çünkü 8K ile sınırlıdır. Bu durumlarda, çalıştırmadan önce komut dosyasını doğrulamanın diğer yolları için bu ipucuna bakın .

Çıktıdan memnun olduğunuzda, rahatsız etmeyin EXEC.


3
Yabancı anahtar kısıtlamalarını birincil anahtarlardan önce bıraktığınızdan da emin olmak isteyebilirsiniz; ORDER BY (CASE WHEN c.[type] IN ('PK', 'UQ') THEN 1 ELSE 0 END)
Daniel Hutmacher

1
@Daniel iyi nokta, SİPARİŞ BY türü, SQL Server yeni kısıtlama türlerini tanıtan kadar muhtemelen yeterli.
Aaron Bertrand

6

Kabul edilen yanıtla başladım ve tam sql deyimini dinamik sql'de oluşturmak yerine bir while döngüsü kullanacak şekilde yapıyı değiştirdim. Bunu birkaç nedenden ötürü daha çok seviyorum.

Sorgu, büyük @sql değişkeninde saklanmaz. Bu uygulama çıktıda günlüğe kaydetme amacıyla bırakılan her kısıtlama için bir Yazdırmaya izin verir. Birim testimde yürütme biraz daha hızlı görünüyordu.

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.