1

以下のテスト スクリプトを使用してチェック制約を作成すると、制約に違反するデータが引き続きテーブルに挿入され、制約が信頼済みとして表示されます。

チェック制約が NULL を正しくチェックしていないことは認識していますが (column = null代わりに が含まれcolumn IS nullています)、チェック条件が false と評価されるため、SQL Server は 'ASDF'、'3'、または NULL 値を許可しないと予想されます。これらの値に対して。このチェック制約が次の値を許可している理由を誰かが説明できますか: NULL、「3」、「ASDF」?

制約条件を に変更すると(checkMe is null or checkMe = '1' or checkMe = '2')、期待どおりに機能します。

SQL Server のバージョン: Microsoft SQL Server 2008 R2 (SP2) - 10.50.4000.0 (X64)

CREATE TABLE dbo.testCheck(checkMe varchar(50));
go

テーブルにデータを挿入する

INSERT INTO dbo.testCheck(checkMe)
VALUES ('1'),('2'),(NULL),('3');
GO

チェック付きの制約を追加して、既存のデータをチェックするようにします。NULL と '3' の両方がこのチェックに違反していると思いますが、何とか成功しています。

ALTER TABLE dbo.testCheck WITH CHECK 
ADD CONSTRAINT ck_testCheck 
CHECK (checkMe = null or checkMe = '1' or checkMe = '2');
GO

チェック制約が追加された後に無効なデータを挿入しようとしています...これは成功しますか?

INSERT INTO dbo.testCheck(checkMe) VALUES('ASDF');
GO

テーブルに無効なデータが含まれていること、およびこの制約が信頼済みとしてマークされていること、つまり、テーブル内のすべてのデータが制約に対して検証されていることを示します

SELECT *
    --this is the same logic as in the check constraint, shows 3 rows that do not pass
    , checkConstraintLogic = case when (checkMe = null or checkMe = '1' or checkMe = '2') then 'PASS' else 'FAIL' end
FROM dbo.testCheck;
go

SELECT parentObject = isnull(OBJECT_SCHEMA_NAME(k.parent_object_id) + '.', '') + OBJECT_NAME(k.parent_object_id)
    , k.name, k.is_not_trusted
FROM sys.check_constraints k 
WHERE k.parent_object_id = object_id('dbo.testCheck')
ORDER BY 1;
GO

スクリプト出力:

出力スクリーンショット

4

2 に答える 2

0

ここで指定されているとおり:

CHECK 制約は、FALSE と評価される値を拒否します。

言い換えると:

CHECK 制約は、チェックしている条件がテーブル内のどの行でも FALSE でない場合に TRUE を返します。

あなたの場合、式(checkMe is null or checkMe = '1' or checkMe = '2')はNULL(別名不明)と評価され、CHECK制約はTRUEを返します(チェックしている条件がFALSEではないため)

同じソースからの良い例:

たとえば、MyColumn に値 10 のみを含めることができる (MyColumn = 10) ことを指定して、int 型の列 MyColumn に制約を設定するとします。値 NULL を MyColumn に挿入すると、データベース エンジンは NULL を挿入し、エラーを返しません。

于 2014-04-10T21:34:48.430 に答える