2

私は(特に)2つの列を持つテーブルを持っています:

NotApplicable  bit
TargetLevel    numeric(5,2)

次のルールが適用される制約を作成する必要があります。

  1. NotApplicable と TargetLevel の両方を NULL にすることはできません
  2. NotApplicable と TargetLevel の両方に値を指定することはできません
  3. NotApplicable または TargetLevel には値が必要です

これは排他的 OR シナリオだと思いますか? しばらく前に試してみましたが、これが上記の最後のシナリオを説明していないことに気付きました。

ALTER TABLE [dbo].[my_Table] ADD CONSTRAINT [DF_tbl_my_Table_notApplicable] DEFAULT ((0)) FOR [notApplicable]
GO
ALTER TABLE [dbo].[my_Table] WITH CHECK ADD CONSTRAINT [CK_tbl_my_Table] CHECK  ((COALESCE([targetLevel],[notapplicable]) IS NOT NULL))
GO
ALTER TABLE [dbo].[my_Table] CHECK CONSTRAINT [CK_tbl_my_Table]
GO

これを完成させるための助けをいただければ幸いです。また、上記の例で実際に必要な最後の ALTER ステートメントはありますか?

4

2 に答える 2

7

少し冗長ですが、私が行う標準的な方法は次のとおりです。

ALTER TABLE T ADD CONSTRAINT CK_One_Or_Tother CHECK (
    (NotApplicable IS NULL and TargetLevel IS NOT NULL) OR
    (NotApplicable IS NOT NULL and TargetLevel IS NULL)
)

また、上記の例で実際に必要な最後の ALTER ステートメントはありますか?

ALTER TABLE [dbo].[my_Table] CHECK CONSTRAINT [CK_tbl_my_Table]

これは、制約を作成または変更して を指定したことがある場合NOCHECK、または他の方法で以前に制約を無効にして現在は有効にしている場合にのみ必要です。制約の作成のデフォルトでは、制約が有効になっています。


正確に 1 つを入力する必要がある多数の列の場合、別の構造に切り替える傾向があります。

ALTER TABLE T ADD CONSTRAINT CK_One_Or_Tother CHECK (
    1 = (
        CASE WHEN ColumnA IS NOT NULL THEN 1 ELSE 0 END +
        CASE WHEN ColumnB IS NOT NULL THEN 1 ELSE 0 END +
        CASE WHEN ColumnC IS NOT NULL THEN 1 ELSE 0 END +
        CASE WHEN ColumnD IS NOT NULL THEN 1 ELSE 0 END
    )
)

これには、各列に 1 回だけ名前を付けるという利点がありますが、見栄えが悪い場合があります。

于 2013-10-28T13:13:23.807 に答える
0

2 列のシナリオの代替構文は次のとおりです。

ALTER TABLE T ADD CONSTRAINT CK_One_Or_Tother CHECK (
     (NotApplicable IS NULL     OR TargetLevel IS NULL)
 AND (NotApplicable IS NOT NULL OR TargetLevel IS NOT NULL)
)
于 2015-03-10T14:28:28.130 に答える