WITH CHECK ADD CONSTRAINT followed by CHECK CONSTRAINT vs. ADD CONSTRAINT

后端 未结 7 1018
天涯浪人
天涯浪人 2020-12-02 06:06

I\'m looking at the AdventureWorks sample database for SQL Server 2008, and I see in their creation scripts that they tend to use the following:

ALTER TABLE          


        
相关标签:
7条回答
  • 2020-12-02 06:47

    WITH NOCHECK is used as well when one has existing data in a table that doesn't conform to the constraint as defined and you don't want it to run afoul of the new constraint that you're implementing...

    0 讨论(0)
  • 2020-12-02 06:59

    To demonstrate how this works--

    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;
    
    0 讨论(0)
  • 2020-12-02 06:59

    Foreign key and check constraints have the concept of being trusted or untrusted, as well as being enabled and disabled. See the MSDN page for ALTER TABLE for full details.

    WITH CHECK is the default for adding new foreign key and check constraints, WITH NOCHECK is the default for re-enabling disabled foreign key and check constraints. It's important to be aware of the difference.

    Having said that, any apparently redundant statements generated by utilities are simply there for safety and/or ease of coding. Don't worry about them.

    0 讨论(0)
  • 2020-12-02 07:01

    The first syntax is redundant - the WITH CHECK is default for new constraints, and the constraint is turned on by default as well.

    This syntax is generated by the SQL management studio when generating sql scripts -- I'm assuming it's some sort of extra redundancy, possibly to ensure the constraint is enabled even if the default constraint behavior for a table is changed.

    0 讨论(0)
  • 2020-12-02 07:02

    WITH CHECK is indeed the default behaviour however it is good practice to include within your coding.

    The alternative behaviour is of course to use WITH NOCHECK, so it is good to explicitly define your intentions. This is often used when you are playing with/modifying/switching inline partitions.

    0 讨论(0)
  • 2020-12-02 07:07

    Further to the above excellent comments about trusted constraints:

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

    An untrusted constraint, much as its name suggests, cannot be trusted to accurately represent the state of the data in the table right now. It can, however, but can be trusted to check data added and modified in the future.

    Additionally, untrusted constraints are disregarded by the query optimiser.

    The code to enable check constraints and foreign key constraints is pretty bad, with three meanings of the word "check".

    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".
    
    0 讨论(0)
提交回复
热议问题