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


208

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

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

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

이게 가능해?


3
이것은 완전한 사본이 아닙니다. 선택한 테이블 만 복사하려고합니다
Maciej

이 작업에 대한 나의 관심은 이것이 당신뿐만 아니라 모든 사람의 제약을 끄는 것입니다. 이 작업을 수행해야하는 경우 데이터베이스를 단일 사용자 모드로 먼저 설정하십시오. 그렇지 않으면 데이터 무결성 문제가 발생할 수 있습니다.
HLGEM 2009

13
미래의 사람들에게 : 데이터베이스의 모든 제약 조건을 한 번에 비활성화하고 다시 활성화 할 수 있습니다. stackoverflow.com/a/161410
brichins

1
완료되면 제약 조건을 활성화하는 것을 잊지 마십시오!
Mike Christian

1
@NicolasBarbulesco 박람회; sql-serverand sql-server-2005태그를 벗어났습니다 . 내가 준 링크는 SQL Server를위한 것이지만 Oracle에서도 동일한 작업을 수행 할 수 있습니다 ( 여기여기 참조) . PostgreSQL 에서도 가능 합니다 .
brichins

답변:


214

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

ALTER TABLE foo NOCHECK CONSTRAINT ALL

또는

ALTER TABLE foo NOCHECK CONSTRAINT CK_foo_column

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


10
그러나 이것은 일시적인 것이 아닙니다.
Nicolas Barbulesco

@NicolasBarbulesco : 그것은 달려 있습니다. 예, DROP / CREATE를 사용하여 다시 활성화 할 수 있다는 점에서
gbn

이 답변은 솔루션의 상반기입니다. 제약 조건을 일시적으로 해제하는 간단한 방법을 찾고 있었고 Oracle에는 존재하지 않는다는 결론에 도달했습니다.
Nicolas Barbulesco

PK 및 고유 제한 조건을 비활성화 할 수 없다는 것은 사실이 아닙니다. 적어도 최신 버전의 SQL Server에서는 작동합니다. 예를 들어, techonthenet.com/sql_server/primary_keys.php를
Dejan

1
오라클의 @NicolasBarbulesco? ALTER TABLE some_table DISABLE CONSTRAINT some_table_fk1; // 제약 조건을 위반하는 몇 가지 작업을 수행합니다. ALTER TABLE some_table ENABLE CONSTRAINT some_table_fk1;
Steve Swinsburg 5

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

1
@kevinc no. 당신이 consitent 인 한 그것은 중요하지 않습니다.
Po-ta-toe

2
따옴표 붙은 식별자를 사용하는 것이 ANSI 표준 설정이라고 생각하므로 문자열에 사용해서는 안됩니다. 일관성을 유지하는 것과는 아무런 관련이 없습니다. 참조 stackoverflow.com/questions/1992314/...
kevinc

1
절차 주셔서 감사합니다! 그리고 올바른 케이스는 "sp_MSforeachtable"(MS 대문자)입니다. 감사!
Sielu

3
질문에 완전히 답변하므로 정답으로 표시되어 있어야합니다. 그뿐만 아니라 @Donal에는 와일드 카드 버전이 포함되어있어 매우 도움이되었습니다.
매트 잭슨

2
재 활성화 비트에 감사드립니다. 특히 check check많은 사람들이 잊어 버리는 더블 !
Alex

57

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

ALTER TABLE foo CHECK CONSTRAINT ALL

또는

ALTER TABLE foo CHECK CONSTRAINT FK_something

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

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

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


11
더 좋은 방법은 체크 체크 제약으로 테이블 푸를 변경하는 것입니다. FK_something
Cody Konior

1
ALTER TABLE foo CHECK CONSTRAINT ALL 또는 ALTER TABLE foo CHECK CONSTRAINT FK_something은 제약 조건을 활성화하지만 데이터를 확인하지 않고 제약 조건을 신뢰할 수 없음을 의미합니다 (is_no_trusted = 1, is_disabled = 0).
Bogdan Sahlean


0

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

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의 제약 조건 및 트리거 비활성화를 참조하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.