2016-05-09 27 views
0

SQL Server 2012 Management Studioを使用しています。以下は私が書かなければならないものです。私は本当にいくつかの助けに感謝します。SQL Server 2012 - チェック制約

ALTER TABLE [tablename] WITH CHECK ADD CONSTRAINT [constraintname] CHECK 
(([column]='A' OR [column]='B' OR [column]='C' OR [column]='D')) 

しかし、我々は、SQL Server 2012 Management Studioを経由スクリプトを生成する際に生成されたスクリプトは、最初のNOCHECKで構成して、テーブルの上にチェックを適用するのはなぜ、私は..

ALTER TABLE [tablename] WITH NOCHECK ADD CONSTRAINT [constraintname] CHECK 
(([column]='A' OR [column]='B' OR [column]='C' OR [column]='D')) 
GO 
ALTER TABLE [tablename] CHECK CONSTRAINT [constraintname] 

を以下の文を取得しています? nocheckなしでチェック制約を作成するとどうなりますか?

答えて

2

生成されるスクリプトではNOCHECKが使用されるため、テーブルの値が準拠していない場合でも、制約は常に作成されます。これは、自動的に生成されたスクリプトの方がデータベーススキーマが正しく作成または修正されるためです。

最初に、生成されたスクリプトの2番目のステートメントは、クエリオプティマイザが制約を考慮することを保証することだと思いました。しかし、さらに調査すると、2番目の声明は効果がないと思われます。私の2番目の答えを見てください。

WITH CHECKを使用して手動で実行しているときは、ステートメントが失敗したことを直ちに確認し、是正処置を取ることができます。次に、ステートメントを再度実行します。

WITH NOCHECKオプションを使用すると、データが無効であることに気付かないことがあります。個人的には、制約を追加するためにALTER TABLEを実行するときは、常にWITH CHECKを使用します。また、Books Onlineでは、WITH NOCHECKを使用することはお勧めできないことを示しています。

まず、テーブルを作成していくつかの値を挿入しましょう。

CREATE TABLE dbo.T 
(
    id int NOT NULL IDENTITY(1,1), 
    [column] nchar(1) NOT NULL 
); 

INSERT INTO dbo.T ([column]) 
    VALUES (N'A'), (N'B'), (N'C'), (N'E'); 

WITH CHECKを指定してテーブルを変更し、制約を追加してください。これは、テーブル内の一部のデータが制約に準拠していないために失敗します。

ALTER TABLE dbo.T 
    WITH CHECK 
    ADD CONSTRAINT CK_Column CHECK ([column] IN (N'A', N'B', N'C', N'D')); 

enter image description here

制約がsys.check_constraintsのシステム・カタログ・ビューを使用して、作成されている場合を見てみましょう。これは、制約が作成されていないことを示しています。

SELECT * 
    FROM sys.check_constraints 
    WHERE [parent_object_id] = OBJECT_ID(N'dbo.T'); 

enter image description here

、再びNOCHECK WITH指定し、この時間を試してみてください。今回は正常に完了します。ただし、テーブル内のデータが無効であるという警告はなく、望ましくない可能性があります。

ALTER TABLE dbo.T 
    WITH NOCHECK 
    ADD CONSTRAINT CK_Column CHECK ([column] IN (N'A', N'B', N'C', N'D')); 

enter image description here

そして、我々はチェック制約が作成されていることを確認することができます。

enter image description here

参照オンラインブック> ALTER TABLE(Transact-SQLの):https://msdn.microsoft.com/en-GB/library/ms190273.aspx> CHECK WITH | WITH NOCHECK

既存のデータに対して新しいCHECKまたはFOREIGN KEY制約を検証しない場合は、WITH NOCHECKを使用します。これを行うことはお勧めできませんが、ごくまれにあります。新しい制約は、後のすべてのデータ更新で評価されます。制約が追加されたときにWITH NOCHECKによって抑制される制約違反は、制約に従わないデータで行を更新すると、将来の更新が失敗する可能性があります。

二自動的に生成されたステートメントの理由はここに明らかにされています

クエリオプティマイザは、NOCHECKで定義された制約を考慮していません。このような制約は、ALTER TABLE表WITH CHECK CHECK CONSTRAINT ALLを使用して再度有効にするまで無視されます。 ...私の前の回答の後に少し深く

を掘る

1

我々はWITH NOCHECKオプションでCHECK制約を作成した後、次のステートメントを実行した場合、我々は、制約が有効になっていることがわかります(is_disabled = 0 )、それは信頼されていません。 SSMSによって生成された第2の文を実行

SELECT name, is_disabled, is_not_trusted 
    FROM sys.check_constraints 
    WHERE [parent_object_id] = OBJECT_ID(N'dbo.T'); 

enter image description here

、違いはありません。チェック制約は依然として信頼されておらず、すでに有効になっています。

ALTER TABLE dbo.T 
    CHECK CONSTRAINT CK_Column; 

データを修正する必要があります。 (または制約を変更してください)

UPDATE dbo.T 
    SET [column] = N'D' 
    WHERE [column] = N'E'; 

このステートメントを実行します。今回はWITH CHECKを指定しているので、データが検証されることに注意してください。

ALTER TABLE dbo.T 
    WITH CHECK 
    CHECK CONSTRAINT CK_Column; 

その後、最終的に我々は、制約は、それがクエリオプティマイザが使用することができることを意味、(0 = is_not_trusted)信頼さとなっていることがわかります。

SELECT name, is_disabled, is_not_trusted 
    FROM sys.check_constraints 
    WHERE [parent_object_id] = OBJECT_ID(N'dbo.T'); 

enter image description here

制約がすでに有効になっているためので、要約すると、SSMSによって生成された2番目のステートメントは、私の知る限りは有用な目的を果たしていません。

参照オンラインブック> sys.check_constraints(のTransact-SQL):https://msdn.microsoft.com/en-GB/library/ms187388.aspx

また、オンラインブックは> ALTER TABLEを参照(のTransact-SQL):https://msdn.microsoft.com/en-GB/library/ms190273.aspx> {CHECK | NOCHECK} CONSTRAINT

constraint_nameが有効か無効かを指定します。このオプションは、FOREIGN KEY制約とCHECK制約でのみ使用できます。 NOCHECKが指定されると、制約は使用不可になり、将来の挿入または更新は制約条件に対して検証されません。DEFAULT、PRIMARY KEY、およびUNIQUE制約を無効にすることはできません。 http://www.sqlservercentral.com/articles/Performance+Tuning/71264/

SQLServerCentral.com>チェックおよび外部キー制約は、クエリのパフォーマンスが向上します