29


SQLで条件付きのnot null制約を作成することは可能ですか? 言い換えれば、長い列 A が含まれている限り列 B を null にすることができるような制約を作成することは可能ですが、列 A の内容が別のものに変更された場合、列 B を null にすることはできなくなりますか?
そしてそれを拡張するために、列Aが「NEW」である限り、列Bがnullまたは空でなければならないようにすることができますか?
ありがとうございました:D

4

4 に答える 4

38

これは、CONSTRAINT CHECK ではまったく問題ありません。これを行うだけです:

要件:

長い列Aが含まれているので、列Bがnullになることができるような制約を作成することは可能ですか?

フレーズに注意してください: 列 Bnull にすることができます

解決:

create table tbl
(
    A varchar(10) not null,
    B varchar(10),

    constraint uk_tbl check
    (
      A = 'NEW' -- B can be null or not null: no need to add AND here
      OR (A <> 'NEW' AND B IS NOT NULL)
    )
);

さらに単純化できます。

create table tbl
(
    A varchar(10) not null,
    B varchar(10),

    constraint uk_tbl check
    (
      A = 'NEW' 
      OR B IS NOT NULL
    )
);

上記の要件と相互に互換性のない要件:

そしてそれを拡張するために、列Aが「NEW」である限り、列Bがnullまたは空でなければならないようにすることができますか?

フレーズに注意してください: 列 Bはnull でなければなりません

create table tbl
(
    A varchar(10) not null,
    B varchar(10),

    constraint uk_tbl check
    (
      (A = 'NEW' AND B IS NULL)
      OR A <> 'NEW'
    )
);

これで単純化できますが、より単純ですが、上記のように読みにくい場合があります。

create table tbl
(
    A varchar(10) not null,
    B varchar(10),

    constraint uk_tbl check
    (
      A <> 'NEW'
      OR B IS NULL
    )
);
于 2012-04-23T01:58:18.470 に答える
2

最初に述べた要件は次のとおりだと思います。

IF ( B IS NULL ) THEN ( A = 'NEW' )

含意書き換え規則を適用します。

IF ( X ) THEN ( Y )   <=>   ( NOT ( X ) OR ( Y ) )

あなたの場合;

( NOT ( B IS NULL ) OR ( A = 'NEW' ) )

SQL 構文を利用するためにマイナーな書き直し:

( B IS NOT NULL OR A = 'NEW' )

2 番目に述べた (「拡張」) 要件:

IF ( A = 'NEW' ) THEN ( B IS NULL )

書き換えルールを適用:

( NOT ( A = 'NEW' ) OR ( B IS NULL ) )

マイナーリライト:

( A <> 'NEW' OR B IS NULL )
于 2012-04-23T08:09:09.280 に答える
1

編集:他の回答で述べたように、最初に提案したトリガーではなく、CHECKが最善の方法です。原文は次のとおりです。


dbaseman が示唆しているように、トリガーは有効な方法です (そうではありません)。このようなことを試してください(テストされていません):

CREATE OR REPLACE TRIGGER test
  BEFORE UPDATE ON table1
FOR EACH ROW
WHEN (new.A = 'NEW' and new.B IS NOT NULL)
   RAISE_APPLICATION_ERROR (
     num=> -20001,
     msg=> 'B must be NULL for new rows (A = NEW)'
);
于 2012-04-23T01:33:13.850 に答える
0

onedaywhenによると、この回答は犯罪的に間違っており、忌まわしいものです。CHECK制約 を使用できます。http://msdn.microsoft.com/en-us/library/ms188258.aspx

条件付き制約を作成する方法はありません。ただし、トリガーを使用してジョブを実行できるはずです。それが彼らの目的です。

http://msdn.microsoft.com/en-us/library/ms189799.aspx

CREATE TRIGGER MyTable.ConditionalNullConstraint ON MyTable.ColumnB
AFTER INSERT
AS
IF EXISTS (SELECT *
    FROM inserted
    WHERE A <> 'NEW' AND B IS NULL
    )
BEGIN
    RAISERROR ('if A is ''NEW'' then B cannot be NULL', 16, 1);
    ROLLBACK TRANSACTION;
END;
GO

クエリでは、テーブルのように動作する特別なオブジェクトであるinsertを参照する必要があることに注意してください。これにより、トリガーの原因となった行を参照できます。

もちろん、この例では、制約を適用するためにAFTER UPDATEも処理する必要がありますが、それが一般的な考え方です。

于 2012-04-23T01:29:26.743 に答える