Làm thế nào để tôi bỏ tất cả các ràng buộc từ tất cả các bảng?


30

Tôi muốn loại bỏ tất cả các ràng buộc mặc định, kiểm tra các ràng buộc, các ràng buộc duy nhất, khóa chính và khóa ngoài từ tất cả các bảng trong cơ sở dữ liệu SQL Server. Tôi biết làm thế nào để có được tất cả các tên ràng buộc từ sys.objects, nhưng làm thế nào để tôi điền vào ALTER TABLEphần đó?


Chỉ vì tò mò, bối cảnh của một yêu cầu như vậy là gì? Đang tự hỏi làm thế nào các phụ thuộc chức năng được giải quyết (ví dụ: các khung nhìn được lập chỉ mục, các sự kiện xếp tầng trên FK và UQ có IGNORE_DUP_KEY = ON).
Solomon Rutzky

3
@srutzky Nó đã được hỏi trên Stack Overflow nhưng tôi đã quyết định tạo một phiên bản chính tắc hơn, sạch hơn ở đây. Dù sao, đó là một yêu cầu chung, thường là một phần của nhiệm vụ lớn hơn là dọn dẹp cơ sở dữ liệu (bắt đầu lại, dọn dẹp các đối tượng bị đặt nhầm vào chủ, v.v.). Tôi không thấy các phụ thuộc chức năng này bị ảnh hưởng bằng cách loại bỏ các ràng buộc - thực tế tôi nghi ngờ rằng trong hầu hết các trường hợp, bức tranh lớn hơn cũng bị cắt bớt hoặc làm rơi các bảng. Bỏ các ràng buộc đầu tiên cho phép điều đó.
Aaron Bertrand

Câu trả lời:


36

Bạn có thể lấy thông tin này một cách dễ dàng bằng cách tham gia sys.tables.object_id = sys.objects.parent_object_idcho các loại đối tượng đó.

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;

PRINTchỉ dành cho nhãn cầu - nếu bạn có nhiều ràng buộc, nó có thể không hiển thị toàn bộ tập lệnh vì nó bị giới hạn ở 8K. Trong những trường hợp đó, hãy xem mẹo này để biết các cách khác để xác thực tập lệnh trước khi chạy.

Một khi bạn hài lòng với đầu ra, bỏ ghi chú EXEC.


3
Bạn cũng có thể muốn đảm bảo bỏ các ràng buộc khóa ngoại trước các khóa chính; ORDER BY (CASE WHEN c.[type] IN ('PK', 'UQ') THEN 1 ELSE 0 END)
Daniel Hutmacher

1
@Daniel điểm tốt, loại ORDER BY có lẽ là đủ cho đến khi SQL Server giới thiệu các loại ràng buộc mới.
Aaron Bertrand

6

Tôi đã bắt đầu với câu trả lời được chấp nhận và sửa đổi cấu trúc để sử dụng vòng lặp while thay vì xây dựng câu lệnh sql đầy đủ trong sql động. Tôi thích điều này tốt hơn vì nhiều lý do.

Truy vấn không được lưu trữ trong biến @sql lớn. Việc triển khai này cho phép In cho từng ràng buộc được loại bỏ cho mục đích ghi nhật ký trong đầu ra. Thực hiện dường như nhanh hơn một chút trong thử nghiệm đơn vị của tôi.

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.