[sql] 제약 조건을 일시적으로 해제 (MS SQL)

모든 DB 제약 조건 (예 : 테이블 관계)을 일시적으로 해제하는 방법을 찾고 있습니다.

하나의 DB 테이블을 다른 DB에 복사 (INSERT 사용)해야합니다. 적절한 순서로 명령을 실행하여 (관계를 깨지 않도록) 달성 할 수 있다는 것을 알고 있습니다.

그러나 검사 제약 조건을 일시적으로 해제하고 작업 완료 후 다시 설정하면 더 쉬울 것입니다.

이게 가능해?



답변

SQL 2005+에서만 FK 및 CHECK 제약 조건을 비활성화 할 수 있습니다 . ALTER TABLE 참조

ALTER TABLE foo NOCHECK CONSTRAINT ALL

또는

ALTER TABLE foo NOCHECK CONSTRAINT CK_foo_column

기본 키와 고유 제약 조건은 비활성화 할 수 없지만 올바르게 이해하면 괜찮습니다.


답변

-- 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'
---------------------------------------------------------


답변

그리고 당신이 당신의 관계를 깨뜨리지 않았고 고아를 소개하지 않았 음을 확인하려면, 수표를 다시 준비한 후에, 즉

ALTER TABLE foo CHECK CONSTRAINT ALL

또는

ALTER TABLE foo CHECK CONSTRAINT FK_something

그런 다음 다시 실행하여 다음과 같이 선택한 열에 대해 업데이트를 수행 할 수 있습니다.

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

그리고 그 시점의 오류는 제약 조건을 충족하지 못하기 때문에 발생합니다.


답변

실제로 단일 SQL 명령에서 모든 데이터베이스 제한 조건을 사용 불가능하게하고 다른 단일 명령을 호출하여 다시 사용할 수 있습니다. 보다:

나는 현재 SQL Server 2005와 함께 일하고 있지만이 방법이 SQL 2000에서도 작동한다는 것을 거의 확신합니다.


답변

모든 외래 키 비활성화 및 활성화

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

먼저 foreignKeyCursor 커서는 외래 키 목록과 테이블 이름을 수집하는 SELECT 문으로 선언됩니다. 다음으로 커서가 열리고 초기 FETCH 문이 실행됩니다. 이 FETCH 문은 첫 번째 행의 데이터를 로컬 변수 @foreignKeyName 및 @tableName으로 읽습니다. 커서를 반복 할 때 @@ FETCH_STATUS에서 0 값을 확인할 수 있으며 이는 페치가 성공했음을 나타냅니다. 이는 루프가 계속 앞으로 이동하여 행 세트에서 각 연속 외래 키를 가져올 수 있음을 의미합니다. @@ FETCH_STATUS는 연결의 모든 커서에 사용 가능합니다. 따라서 여러 커서를 반복하는 경우 FETCH 문 바로 다음 명령문에서 @@ FETCH_STATUS 값을 확인해야합니다. @@ FETCH_STATUS는 연결에서 가장 최근의 FETCH 작업 상태를 반영합니다. @@ FETCH_STATUS의 유효한 값은 다음과 같습니다.

0 = FETCH 성공
-1 = FETCH 실패
-2 = 페치 된 행이 누락 됨

루프 내에서 코드는 외래 키 제약 조건 (CHECK 또는 NOCHECK 키워드 사용)의 사용 여부에 따라 ALTER TABLE 명령을 다르게 작성합니다. 그러면 명령문이 메시지로 인쇄되어 진행 상황을 관찰 한 다음 명령문이 실행됩니다. 마지막으로 모든 행이 반복되면 저장 프로 시저가 커서를 닫고 할당을 해제합니다.

MSDN Magazine의 제약 조건 및 트리거 비활성화를 참조하십시오.


답변