Bagaimana cara menghapus semua batasan dari semua tabel?

30

Saya ingin menghapus semua batasan default, memeriksa batasan, batasan unik, kunci primer dan kunci asing dari semua tabel dalam database SQL Server. Saya tahu cara mendapatkan semua nama kendala sys.objects, tetapi bagaimana cara mengisi ALTER TABLEbagian itu?

Aaron Bertrand
sumber
Hanya karena penasaran, apa konteks dari permintaan seperti itu? Saya bertanya-tanya bagaimana dependensi fungsional ditangani (yaitu tampilan yang diindeks, kejadian kaskade pada FK, dan UQ yang memiliki IGNORE_DUP_KEY = ON).
Solomon Rutzky
3
@rutzky Ditanyakan pada Stack Overflow tapi saya memutuskan untuk membuat versi yang lebih bersih dan kanonik di sini. Bagaimanapun itu adalah permintaan umum, seringkali merupakan bagian dari tugas yang lebih besar untuk membersihkan database (memulai kembali, membersihkan objek yang keliru dimasukkan ke dalam master, dll). Saya tidak melihat ketergantungan fungsional ini dipengaruhi oleh menjatuhkan batasan - sebenarnya saya menduga bahwa dalam kebanyakan kasus gambar yang lebih besar memotong atau menjatuhkan tabel juga. Menjatuhkan kendala terlebih dahulu memungkinkan itu.
Aaron Bertrand

Jawaban:

36

Anda dapat memperoleh informasi ini dengan mudah dengan bergabung sys.tables.object_id = sys.objects.parent_object_iduntuk jenis objek tersebut.

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;

PRINTada hanya untuk eyeballing - jika Anda memiliki banyak kendala, itu mungkin tidak menunjukkan seluruh skrip karena terbatas pada 8K. Dalam kasus tersebut, lihat tip ini untuk cara lain untuk memvalidasi skrip sebelum menjalankan.

Setelah Anda puas dengan hasilnya, batalkan komentar pada EXEC.

Aaron Bertrand
sumber
3
Anda mungkin juga ingin memastikan untuk menjatuhkan batasan kunci asing sebelum kunci utama; ORDER BY (CASE WHEN c.[type] IN ('PK', 'UQ') THEN 1 ELSE 0 END)
Daniel Hutmacher
1
Poin bagus @aniel, tipe ORDER BY mungkin cukup sampai SQL Server memperkenalkan tipe kendala baru.
Aaron Bertrand
6

Saya mulai dengan jawaban yang diterima dan memodifikasi struktur untuk menggunakan loop sementara daripada membangun pernyataan sql penuh dalam sql dinamis. Saya suka ini lebih baik karena beberapa alasan.

Permintaan tidak disimpan dalam variabel @sql besar. Implementasi ini memungkinkan Cetak untuk setiap kendala yang dijatuhkan untuk tujuan logging di output. Eksekusi tampak sedikit lebih cepat dalam pengujian unit saya.

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
sumber