Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Tạm thời vô hiệu hóa tất cả các ràng buộc khóa ngoại

Để tắt các ràng buộc khóa ngoại:

DECLARE @sql NVARCHAR(MAX) = N'';

;WITH x AS 
(
  SELECT DISTINCT obj = 
      QUOTENAME(OBJECT_SCHEMA_NAME(parent_object_id)) + '.' 
    + QUOTENAME(OBJECT_NAME(parent_object_id)) 
  FROM sys.foreign_keys
)
SELECT @sql += N'ALTER TABLE ' + obj + ' NOCHECK CONSTRAINT ALL;
' FROM x;

EXEC sp_executesql @sql;

Để bật lại:

DECLARE @sql NVARCHAR(MAX) = N'';

;WITH x AS 
(
  SELECT DISTINCT obj = 
      QUOTENAME(OBJECT_SCHEMA_NAME(parent_object_id)) + '.' 
    + QUOTENAME(OBJECT_NAME(parent_object_id)) 
  FROM sys.foreign_keys
)
SELECT @sql += N'ALTER TABLE ' + obj + ' WITH CHECK CHECK CONSTRAINT ALL;
' FROM x;

EXEC sp_executesql @sql;

Tuy nhiên, bạn sẽ không thể cắt ngắn các bảng, bạn sẽ phải xóa khỏi chúng theo đúng thứ tự. Nếu bạn cần cắt ngắn chúng, bạn cần loại bỏ hoàn toàn các ràng buộc và tạo lại chúng. Điều này đơn giản để thực hiện nếu các ràng buộc khóa ngoại của bạn đều là các ràng buộc cột đơn, nhưng chắc chắn sẽ phức tạp hơn nếu có nhiều cột liên quan.

Đây là một cái gì đó bạn có thể thử. Để biến điều này thành một phần của gói SSIS, bạn sẽ cần một nơi để lưu trữ các định nghĩa FK trong khi gói SSIS chạy (bạn sẽ không thể thực hiện tất cả trong một tập lệnh). Vì vậy, trong một số cơ sở dữ liệu tiện ích, hãy tạo một bảng:

CREATE TABLE dbo.PostCommand(cmd NVARCHAR(MAX));

Sau đó, trong cơ sở dữ liệu của bạn, bạn có thể có một thủ tục được lưu trữ để thực hiện việc này:

DELETE other_database.dbo.PostCommand;

DECLARE @sql NVARCHAR(MAX) = N'';

SELECT @sql += N'ALTER TABLE ' + QUOTENAME(OBJECT_SCHEMA_NAME(fk.parent_object_id))
   + '.' + QUOTENAME(OBJECT_NAME(fk.parent_object_id)) 
   + ' ADD CONSTRAINT ' + fk.name + ' FOREIGN KEY (' 
   + STUFF((SELECT ',' + c.name
    FROM sys.columns AS c 
        INNER JOIN sys.foreign_key_columns AS fkc 
        ON fkc.parent_column_id = c.column_id
        AND fkc.parent_object_id = c.[object_id]
    WHERE fkc.constraint_object_id = fk.[object_id]
    ORDER BY fkc.constraint_column_id 
    FOR XML PATH(''), TYPE).value('.', 'nvarchar(max)'), 1, 1, '')
+ ') REFERENCES ' + 
QUOTENAME(OBJECT_SCHEMA_NAME(fk.referenced_object_id))
+ '.' + QUOTENAME(OBJECT_NAME(fk.referenced_object_id))
+ '(' + 
STUFF((SELECT ',' + c.name
    FROM sys.columns AS c 
        INNER JOIN sys.foreign_key_columns AS fkc 
        ON fkc.referenced_column_id = c.column_id
        AND fkc.referenced_object_id = c.[object_id]
    WHERE fkc.constraint_object_id = fk.[object_id]
    ORDER BY fkc.constraint_column_id 
    FOR XML PATH(''), TYPE).value('.', 'nvarchar(max)'), 1, 1, '') + ');
' FROM sys.foreign_keys AS fk
WHERE OBJECTPROPERTY(parent_object_id, 'IsMsShipped') = 0;

INSERT other_database.dbo.PostCommand(cmd) SELECT @sql;

IF @@ROWCOUNT = 1
BEGIN
  SET @sql = N'';

  SELECT @sql += N'ALTER TABLE ' + QUOTENAME(OBJECT_SCHEMA_NAME(fk.parent_object_id))
    + '.' + QUOTENAME(OBJECT_NAME(fk.parent_object_id)) 
    + ' DROP CONSTRAINT ' + fk.name + ';
  ' FROM sys.foreign_keys AS fk;

  EXEC sp_executesql @sql;
END

Bây giờ khi gói SSIS của bạn hoàn tất, nó sẽ gọi một thủ tục được lưu trữ khác, quy trình này thực hiện:

DECLARE @sql NVARCHAR(MAX);

SELECT @sql = cmd FROM other_database.dbo.PostCommand;

EXEC sp_executesql @sql;

Nếu bạn đang làm tất cả những điều này chỉ vì mục đích có thể cắt bớt thay vì xóa, tôi khuyên bạn chỉ cần thực hiện lần truy cập và chạy xóa. Có thể sử dụng mô hình khôi phục đã ghi nhật ký hàng loạt để giảm thiểu tác động của nhật ký. Nói chung, tôi không thấy giải pháp này sẽ nhanh hơn nhiều so với việc chỉ sử dụng thao tác xóa theo đúng thứ tự.

Vào năm 2014, tôi đã xuất bản một bài viết chi tiết hơn về điều này tại đây:

  • Bỏ và tạo lại tất cả các ràng buộc về khóa ngoại trong SQL Server


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Loại bỏ một máy chủ được liên kết trong SQL Server bằng T-SQL

  2. Cách đổi tên cơ sở dữ liệu trong SQL Server - Hướng dẫn SQL Server / TSQL Phần 26

  3. Hàm so với Thủ tục được lưu trữ trong SQL Server

  4. Thủ tục được lưu trữ - trả về danh tính dưới dạng tham số đầu ra hoặc đại lượng vô hướng

  5. Khắc phục sự cố sao chép SQL Server