誰でも次のコードの第3の挿入物(クエリデータ)がSQL Serverで許可されている理由を説明できますか?チェックイン制約がこのnull挿入を停止しないのはなぜですか?
私の知る限り、チェック制約はのみ許可する必要があります。
Code
がnullで、System
はnullです。Code
はnullではなく、System
は1
です。
私が最初に考えたのはANSI NULLS
だったが、それらの設定on
またはoff
には差は行われません。
これは、アプリケーションで見つかったより大きな問題の簡略化した例です(システムは数字のリストと照合してチェックされました - IN(1, 2, etc.)
)。このチェックを、外部キー(IN
ではなく)と置き換えました。新しい検査制約は、nullまたはnullでないどちらかを許可しました。そうすることで3番目のインサートができなくなりました。
IF EXISTS (SELECT * FROM sys.check_constraints WHERE object_id = OBJECT_ID(N'[dbo].[CK_TestCheck]') AND parent_object_id = OBJECT_ID(N'[dbo].[TestCheck]'))
ALTER TABLE [dbo].[TestCheck] DROP CONSTRAINT [CK_TestCheck]
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[TestCheck]') AND type in (N'U'))
DROP TABLE [dbo].[TestCheck]
GO
SET ANSI_NULLS ON
GO
CREATE TABLE TestCheck(
[Id] [int] IDENTITY(1,1) NOT NULL,
[Code] [varchar](50) NULL,
[System] [tinyint] NULL,
PRIMARY KEY CLUSTERED ([Id] ASC))
GO
ALTER TABLE [dbo].[TestCheck] WITH CHECK ADD CONSTRAINT [CK_TestCheck] CHECK
(
([Code] IS NULL AND [System] IS NULL) --Both null
OR
([Code] IS NOT NULL AND [System] = 1) --Both not null ????
)
GO
ALTER TABLE [dbo].[TestCheck] CHECK CONSTRAINT [CK_TestCheck]
GO
--Good Data
insert TestCheck (Code, [System]) Values(null, null);
insert TestCheck (Code, [System]) Values('123', 1);
--Query Data
insert TestCheck (Code, [System]) Values('123', null);
--Bad data stopped
insert TestCheck (Code, [System]) Values(null, 1);
insert TestCheck (Code, [System]) Values('123', 4);
select * from TestCheck
Where
case when
(
([Code] IS NULL AND [System] IS NULL) --Both null
OR
([Code] IS NOT NULL AND [System] in (1, 2, 3)) --Both not null ????
)
then 0 else 1 end
= 1
未定義の後に(偽)をかっこで囲みません。それは間違いではありません。 –
@Damien_The_Unbeliever - 私はあなたが何を意味しているのか知っていますが、最終結果に向かって「未定義」が何をしているかについては括弧で追加しました。私は答えにこのコメントを追加します。 –
しかし、あなたが追加したものは真実ではありません。チェック制約の最終結果が「UNKNOWN」の場合は、TRUEと評価された場合と同じように扱われます。つまり、OPを驚かせました。 –