167

Tôi đang tìm cách tạm thời tắt tất cả các ràng buộc của DB (ví dụ: các mối quan hệ bảng).Tắt các ràng buộc tạm thời (MS SQL)

Tôi cần sao chép (sử dụng INSERT) một bảng của DB sang một DB khác. Tôi biết tôi có thể đạt được điều đó bằng cách thực hiện các lệnh theo thứ tự đúng (để không phá vỡ các mối quan hệ).

Nhưng sẽ dễ dàng hơn nếu tôi có thể tắt tạm thời việc kiểm tra và bật lại sau khi kết thúc thao tác.

Điều này có khả thi không?

+3

Đây không phải là bản sao hoàn chỉnh tôi chỉ muốn sao chép các bảng được chọn giữa – Maciej

+13

người thân mến từ Tương lai: Bạn có thể vô hiệu hóa và kích hoạt lại tất cả những hạn chế trong cơ sở dữ liệu cùng một lúc; xem http://stackoverflow.com/a/161410 – brichins

+1

Đừng quên bật các ràng buộc, khi hoàn tất! –

Trả lời

184

Bạn có thể vô hiệu hóa các ràng buộc FK và CHECK chỉ trong SQL 2005+ . Xem ALTER TABLE

ALTER TABLE foo NOCHECK CONSTRAINT ALL 

hoặc

ALTER TABLE foo NOCHECK CONSTRAINT CK_foo_column 

phím Tiểu học và ràng buộc duy nhất không thể bị vô hiệu hóa, nhưng điều này nên được OK nếu tôi đã hiểu bạn một cách chính xác.

+1

Nhưng đây không phải là tạm thời. –

+0

@NicolasBarbulesco: nó phụ thuộc. Có, đó là, bạn có thể kích hoạt lại chúng với DROP/CREATE – gbn

+0

Câu trả lời này chỉ là nửa đầu của giải pháp. Tôi đã tìm kiếm một cách đơn giản để tắt các ràng buộc tạm thời, và tôi đã đạt đến kết luận rằng nó không tồn tại, trên Oracle. –

55

Và, nếu bạn muốn xác minh rằng bạn không bị phá vỡ mối quan hệ của bạn và giới thiệu trẻ em mồ côi, một khi bạn đã tái vũ trang kiểm tra của bạn, ví dụ:

ALTER TABLE foo CHECK CONSTRAINT ALL 

hoặc

ALTER TABLE foo CHECK CONSTRAINT FK_something 

sau đó bạn có thể chạy lại và thực hiện cập nhật đối với bất kỳ cột được chọn nào như vậy:

UPDATE myUpdatedTable SET someCol = someCol, fkCol = fkCol, etc = etc 

Và mọi lỗi tại tại thời điểm sẽ là do không đáp ứng các ràng buộc.

+9

Một cách tốt hơn là ALTER BẢNG FOO VỚI KIỂM TRA KIỂM TRA KIỂM TRA FK_something –

+1

ALTER TABLE foo KIỂM TRA TẤT CẢ hoặc ALTER BẢNG foo CHECK CONSTRAINT FK_something sẽ cho phép ràng buộc nhưng không kiểm tra dữ liệu và điều này có nghĩa là ràng buộc sẽ không tin cậy (is_no_trusted = 1, is_disabled = 0). –

16

Bạn thực sự có thể vô hiệu hóa tất cả các ràng buộc cơ sở dữ liệu trong một lệnh SQL và kích hoạt lại chúng gọi một lệnh khác. Xem:

Tôi hiện đang làm việc với SQL Server 2005 nhưng tôi gần như chắc chắn rằng phương pháp này làm việc với SQL 2000 cũng

2

Vô hiệu hóa và kích hoạt tất cả Keys nước ngoài

CREATE PROCEDURE pr_Disable_Triggers_v2 
    @disable BIT = 1 
AS 
    DECLARE @sql VARCHAR(500) 
     , @tableName VARCHAR(128) 
     , @tableSchema VARCHAR(128) 

    -- List of all tables 
    DECLARE triggerCursor CURSOR FOR 
     SELECT t.TABLE_NAME AS TableName 
      , t.TABLE_SCHEMA AS TableSchema 
     FROM INFORMATION_SCHEMA.TABLES t 
     ORDER BY t.TABLE_NAME, t.TABLE_SCHEMA 

    OPEN triggerCursor 
    FETCH NEXT FROM triggerCursor INTO @tableName, @tableSchema 
    WHILE (@@FETCH_STATUS = 0) 
    BEGIN 

     SET @sql = 'ALTER TABLE ' + @tableSchema + '.[' + @tableName + '] ' 
     IF @disable = 1 
      SET @sql = @sql + ' DISABLE TRIGGER ALL' 
     ELSE 
      SET @sql = @sql + ' ENABLE TRIGGER ALL' 

     PRINT 'Executing Statement - ' + @sql 
     EXECUTE (@sql) 

     FETCH NEXT FROM triggerCursor INTO @tableName, @tableSchema 

    END 

    CLOSE triggerCursor 
    DEALLOCATE triggerCursor 

Đầu tiên, con trỏ ForeignKeyCursor được khai báo là câu lệnh SELECT tập hợp danh sách các khóa ngoài và tên bảng của chúng. Tiếp theo, con trỏ được mở và câu lệnh FETCH ban đầu được thực hiện. Câu hỏi FETCH này sẽ đọc dữ liệu của hàng đầu tiên vào các biến địa phương @foreignKeyName và @tableName. Khi lặp qua con trỏ , bạn có thể kiểm tra @@ FETCH_STATUS với giá trị bằng 0, trong đó cho biết tìm nạp đã thành công. Điều này có nghĩa là vòng lặp sẽ tiếp tục di chuyển về phía trước để nó có thể nhận được mỗi khóa ngoại tiếp theo từ rowset. @@ FETCH_STATUS có sẵn cho tất cả các con trỏ trên kết nối .Vì vậy, nếu bạn đang lặp qua nhiều con trỏ, nó là quan trọng để kiểm tra giá trị của @@ FETCH_STATUS trong tuyên bố ngay sau câu lệnh FETCH. @@ FETCH_STATUS sẽ phản ánh trạng thái cho hoạt động FETCH gần đây nhất trên kết nối. giá trị hợp lệ cho @@ FETCH_STATUS là:

0 = FETCH được thành công
-1 = FETCH không thành công
-2 = hàng mà là lấy thiếu

Bên trong vòng lặp, mã xây dựng các ALTER TABLE lệnh khác nhau tùy thuộc vào ý định là để vô hiệu hóa hoặc kích hoạt các ràng buộc khóa nước ngoài (sử dụng CHECK hoặc NOCHECK từ khóa). Tuyên bố là sau đó được in dưới dạng tin nhắn để tiến trình của nó có thể được quan sát và sau đó câu lệnh được thực thi. Cuối cùng, khi tất cả các hàng đã được lặp lại , quy trình được lưu sẽ đóng và giải quyết con trỏ.

thấy Disabling Constraints and Triggers from MSDN Magazine

137
-- Disable the constraints on a table called tableName: 
ALTER TABLE tableName NOCHECK CONSTRAINT ALL 

-- Re-enable the constraints on a table called tableName: 
ALTER TABLE tableName WITH CHECK CHECK CONSTRAINT ALL 
--------------------------------------------------------- 

-- Disable constraints for all tables: 
EXEC sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT all' 

-- Re-enable constraints for all tables: 
EXEC sp_msforeachtable 'ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all' 
--------------------------------------------------------- 
+0

Tôi nghĩ rằng các cuộc gọi thủ tục lưu trữ của bạn nên có dấu nháy đơn? – kevinc

+1

@kevinc no. Miễn là bạn là người bảo thủ, điều đó không quan trọng. –

+2

Sử dụng số nhận dạng được trích dẫn là tôi tin rằng cài đặt tiêu chuẩn ANSI, có nghĩa là bạn không nên sử dụng chúng cho chuỗi. Không có gì để làm với sự nhất quán. xem http://stackoverflow.com/questions/1992314/what-is-the-difference-between-single-and-double-quotes-in-sql – kevinc

Các vấn đề liên quan