source

Check Add 구속조건 뒤에 Check 구속조건 vs. 구속조건 추가

ittop 2023. 4. 7. 21:56
반응형

Check Add 구속조건 뒤에 Check 구속조건 vs. 구속조건 추가

SQL Server 2008용 AdventureWorks 샘플 데이터베이스를 보고 있는데 작성 스크립트에서 다음 항목을 사용하는 경향이 있습니다.

ALTER TABLE [Production].[ProductCostHistory] WITH CHECK ADD 
CONSTRAINT [FK_ProductCostHistory_Product_ProductID] FOREIGN KEY([ProductID])
  REFERENCES [Production].[Product] ([ProductID])
GO

바로 뒤에 다음과 같이 표시됩니다.

ALTER TABLE [Production].[ProductCostHistory] CHECK CONSTRAINT     
[FK_ProductCostHistory_Product_ProductID]
GO

키(여기서와 ), , 및 통상의 「」(이러한 제약 조건), 「이러한」(이러한 제약 조건), 「이러한」(이러한 제약 조건), 「이러한 제약」(이러한 조건), 「이러한 조건)에 대해서 볼 수 있습니다.CHECK '제약속""DEFAULT제약조건은 다음과 같은 일반적인 형식을 사용합니다.

ALTER TABLE [Production].[ProductCostHistory] ADD  CONSTRAINT  
[DF_ProductCostHistory_ModifiedDate]  DEFAULT (getdate()) FOR [ModifiedDate]
GO

만약 있다면 첫 번째 방법과 두 번째 방법의 차이는 무엇입니까?

입니다.WITH CHECK는 새로운 제약조건의 경우 디폴트이며, 이 제약조건도 디폴트로 유효하게 되어 있습니다.

이 구문은 SQL Management Studio에서 SQL 스크립트를 생성할 때 생성됩니다.아마 테이블의 기본 제약조건 동작이 변경되어도 제약조건이 활성화되도록 하기 위한 추가 용장성일 것입니다.

이게 어떻게 돌아가는지 보여드리기 위해서...

CREATE TABLE T1 (ID INT NOT NULL, SomeVal CHAR(1));
ALTER TABLE T1 ADD CONSTRAINT [PK_ID] PRIMARY KEY CLUSTERED (ID);

CREATE TABLE T2 (FKID INT, SomeOtherVal CHAR(2));

INSERT T1 (ID, SomeVal) SELECT 1, 'A';
INSERT T1 (ID, SomeVal) SELECT 2, 'B';

INSERT T2 (FKID, SomeOtherVal) SELECT 1, 'A1';
INSERT T2 (FKID, SomeOtherVal) SELECT 1, 'A2';
INSERT T2 (FKID, SomeOtherVal) SELECT 2, 'B1';
INSERT T2 (FKID, SomeOtherVal) SELECT 2, 'B2';
INSERT T2 (FKID, SomeOtherVal) SELECT 3, 'C1';  --orphan
INSERT T2 (FKID, SomeOtherVal) SELECT 3, 'C2';  --orphan

--Add the FK CONSTRAINT will fail because of existing orphaned records
ALTER TABLE T2 ADD CONSTRAINT FK_T2_T1 FOREIGN KEY (FKID) REFERENCES T1 (ID);   --fails

--Same as ADD above, but explicitly states the intent to CHECK the FK values before creating the CONSTRAINT
ALTER TABLE T2 WITH CHECK ADD CONSTRAINT FK_T2_T1 FOREIGN KEY (FKID) REFERENCES T1 (ID);    --fails

--Add the CONSTRAINT without checking existing values
ALTER TABLE T2 WITH NOCHECK ADD CONSTRAINT FK_T2_T1 FOREIGN KEY (FKID) REFERENCES T1 (ID);  --succeeds
ALTER TABLE T2 CHECK CONSTRAINT FK_T2_T1;   --succeeds since the CONSTRAINT is attributed as NOCHECK

--Attempt to enable CONSTRAINT fails due to orphans
ALTER TABLE T2 WITH CHECK CHECK CONSTRAINT FK_T2_T1;    --fails

--Remove orphans
DELETE FROM T2 WHERE FKID NOT IN (SELECT ID FROM T1);

--Enabling the CONSTRAINT succeeds
ALTER TABLE T2 WITH CHECK CHECK CONSTRAINT FK_T2_T1;    --succeeds; orphans removed

--Clean up
DROP TABLE T2;
DROP TABLE T1;

또한 신뢰할 수 있는 제약조건에 대한 위의 훌륭한 코멘트도 있습니다.

select * from sys.foreign_keys where is_not_trusted = 1 ;
select * from sys.check_constraints where is_not_trusted = 1 ;

신뢰할 수 없는 제약 조건은 이름에서 알 수 있듯이 현재 테이블 내의 데이터 상태를 정확하게 나타내기 위해 신뢰할 수 없습니다.그러나 나중에 추가 및 수정된 데이터를 확인할 수 있습니다.

또한 신뢰할 수 없는 제약은 쿼리 옵티마이저에 의해 무시됩니다.

체크 제약 및 외부 키 제약 조건을 활성화하는 코드는 "체크"라는 세 가지 의미로 매우 불량합니다.

ALTER TABLE [Production].[ProductCostHistory] 
WITH CHECK -- This means "Check the existing data in the table".
CHECK CONSTRAINT -- This means "enable the check or foreign key constraint".
[FK_ProductCostHistory_Product_ProductID] -- The name of the check or foreign key constraint, or "ALL".

WITH NOCHECK정의된 제약조건에 부합하지 않는 기존 데이터가 테이블에 있고 구현 중인 새로운 제약조건에 반하여 실행되지 않도록 하는 경우에도 사용됩니다.

WITH CHECK는 기본 동작이지만 코딩에 포함하는 것이 좋습니다.

대체 동작은 물론 다음 명령을 사용하는 것입니다.WITH NOCHECK을 사용법이는 인라인 파티션을 사용하여 재생/변경/스위칭할 때 자주 사용됩니다.

외부 키 및 체크 제약 조건에는 신뢰 또는 비신뢰 및 활성화 및 비활성화라는 개념이 있습니다.MSDN 의 .ALTER TABLE세한것 、 을을해해요요 。

WITH CHECK는, 키 및 제약 입니다.「 」 、 「 」 。WITH NOCHECK디폴트로는 비활성화된 외부 키 재설치 및 제약조건 체크입니다.그 차이를 아는 것이 중요합니다.

그러나 유틸리티에 의해 생성되는 명백한 중복 문장은 단순히 안전 및/또는 코딩의 용이성을 위해 존재한다.그것들 걱정은 하지 마세요.

다음은 데이터베이스에서 신뢰할 수 없는 제약조건을 식별하고 수정하는 데 도움이 되도록 작성한 코드입니다.각 문제를 수정하기 위한 코드를 생성합니다.

    ;WITH Untrusted (ConstraintType, ConstraintName, ConstraintTable, ParentTable, IsDisabled, IsNotForReplication, IsNotTrusted, RowIndex) AS
(
    SELECT 
        'Untrusted FOREIGN KEY' AS FKType
        , fk.name AS FKName
        , OBJECT_NAME( fk.parent_object_id) AS FKTableName
        , OBJECT_NAME( fk.referenced_object_id) AS PKTableName 
        , fk.is_disabled
        , fk.is_not_for_replication
        , fk.is_not_trusted
        , ROW_NUMBER() OVER (ORDER BY OBJECT_NAME( fk.parent_object_id), OBJECT_NAME( fk.referenced_object_id), fk.name) AS RowIndex
    FROM 
        sys.foreign_keys fk 
    WHERE 
        is_ms_shipped = 0 
        AND fk.is_not_trusted = 1       

    UNION ALL

    SELECT 
        'Untrusted CHECK' AS KType
        , cc.name AS CKName
        , OBJECT_NAME( cc.parent_object_id) AS CKTableName
        , NULL AS ParentTable
        , cc.is_disabled
        , cc.is_not_for_replication
        , cc.is_not_trusted
        , ROW_NUMBER() OVER (ORDER BY OBJECT_NAME( cc.parent_object_id), cc.name) AS RowIndex
    FROM 
        sys.check_constraints cc 
    WHERE 
        cc.is_ms_shipped = 0
        AND cc.is_not_trusted = 1

)
SELECT 
    u.ConstraintType
    , u.ConstraintName
    , u.ConstraintTable
    , u.ParentTable
    , u.IsDisabled
    , u.IsNotForReplication
    , u.IsNotTrusted
    , u.RowIndex
    , 'RAISERROR( ''Now CHECKing {%i of %i)--> %s ON TABLE %s'', 0, 1' 
        + ', ' + CAST( u.RowIndex AS VARCHAR(64))
        + ', ' + CAST( x.CommandCount AS VARCHAR(64))
        + ', ' + '''' + QUOTENAME( u.ConstraintName) + '''' 
        + ', ' + '''' + QUOTENAME( u.ConstraintTable) + '''' 
        + ') WITH NOWAIT;'
    + 'ALTER TABLE ' + QUOTENAME( u.ConstraintTable) + ' WITH CHECK CHECK CONSTRAINT ' + QUOTENAME( u.ConstraintName) + ';' AS FIX_SQL
FROM Untrusted u
CROSS APPLY (SELECT COUNT(*) AS CommandCount FROM Untrusted WHERE ConstraintType = u.ConstraintType) x
ORDER BY ConstraintType, ConstraintTable, ParentTable;

굳이 말씀드리면, SSMS(반전 로직) 버그인 것 같습니다.디폴트된 첫 번째(new/'with-check'가 아니라 두 번째(기존/재활성화 제약) 스테이트먼트에 'WITH CHECK'의 명시적인 포함/사용이 필요합니다.

두 번째 시나리오가 아닌 잘못된 SQL 문/첫 번째 T-SQL 문에 'WITH CHECK' 절의 생성을 적용한 것인지 궁금합니다. 두 시나리오 모두에 대해 체크를 디폴트로 사용하려고 하는 것인지, 아니면 기존 제약 조건의 재활성화(재활성화)를 적용하려고 하는 것인지 궁금합니다.

(체크 제약이 비활성화되어 있는 시간이 길어질수록 파손/체크 제약 무효 데이터가 그 사이에 침입했을 가능성이 이론적으로 높아집니다.)

언급URL : https://stackoverflow.com/questions/529941/with-check-add-constraint-followed-by-check-constraint-vs-add-constraint

반응형