SQL Serverでは、CHECK
を作成できます 1つ以上の列で受け入れ可能なデータ値を指定するためのテーブルの制約。
テーブルにCHECK
がある場合 制約があり、CHECK
に準拠していないデータを提供しようとしている 制約がある場合、操作はエラーで失敗します。
これは、無効なデータがデータベースに入るのを防ぐのに役立つため、データの整合性を維持するのに役立ちます。
CHECK
を作成するとき 制約、TRUE
を返す論理式を提供します またはFALSE
。この論理式は、データをチェックするために使用されるものです。
CHECK
制約は、列に配置される値を制御するため、外部キー制約に似ています。ただし、違いは、どの値が有効であるかを判断する方法にあります。外部キー制約は、別のテーブルから有効な値のリストを取得しますが、CHECK
制約は、論理式から有効な値を決定します。
制約は、列レベルまたはテーブルレベルで定義できます。列レベルの制約は、その列のデータにのみ適用されます。テーブルレベルの制約が行全体に適用され、複数の列のデータをチェックします。
以下は、列レベルとテーブルレベルの両方のCHECK
を作成する例です。 制約。
例1-列レベルのチェック制約を作成する
これは、基本的な列レベルのCHECK
を作成する例です。 テーブル作成時の制約。
CREATE TABLE ConstraintTest ( ConstraintTestId int IDENTITY(1,1) NOT NULL PRIMARY KEY, Price smallmoney NOT NULL, CONSTRAINT chkPrice CHECK (Price > 0) );
この場合、CHECK
制約は、Price
内のすべてのデータを指定します 列は0より大きくする必要があります。つまり、価格をゼロにすることはできず、負にすることもできません。これは、1つの列のデータに適用されるため、列レベルの制約です。
これは列レベルの制約であるため、列の一部として(コンマなしで)定義することもできます。だから私はこれを行うことができた:
CREATE TABLE ConstraintTest ( ConstraintTestId int IDENTITY(1,1) NOT NULL PRIMARY KEY, Price smallmoney NOT NULL CONSTRAINT chkPrice CHECK (Price > 0) );
いずれにせよ、無効な値を挿入してみましょう:
INSERT INTO ConstraintTest ( Price ) VALUES ( 0 );
結果:
Msg 547, Level 16, State 0, Line 1 The INSERT statement conflicted with the CHECK constraint "chkPrice". The conflict occurred in database "Test", table "dbo.ConstraintTest", column 'Price'.
例2–列と別の列レベルのチェック制約を追加する
テーブルにさらに列を追加してから、別の列レベルのCHECK
を追加しましょう。 制約。
ALTER TABLE ConstraintTest ADD TeamSize tinyint NOT NULL, StartDate date NOT NULL, EndDate date NOT NULL, CONSTRAINT chkTeamSize CHECK (TeamSize >= 3 AND TeamSize <= 15) ;
新しい列の1つは、チームメンバーの数を記録します。この場合、ビジネスルールでは、チームのメンバーは3人以上、15人以下である必要があります。したがって、データベースは、チームのメンバーが3人未満または15人を超える状況を防ぐ必要があります。
無効な値を挿入してみましょう:
INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate ) VALUES ( 1, 2, '2020-01-01', '1900-02-02' );
結果:
Msg 547, Level 16, State 0, Line 1 The INSERT statement conflicted with the CHECK constraint "chkTeamSize". The conflict occurred in database "Test", table "dbo.ConstraintTest", column 'TeamSize'.
例3–テーブルレベルのチェック制約を追加する
次に、テーブルレベルの制約を追加しましょう。これにより、2列のデータがチェックされます。
ちなみに、CHECK
を追加するために別の列を追加する必要はありません 制約。制約を単独で追加するだけです。
例:
ALTER TABLE ConstraintTest ADD CONSTRAINT chkValidEndDate CHECK (EndDate >= StartDate) ;
この場合、終了日が開始日より前になることがないように制約を追加します。これは2つの列にまたがるデータをチェックしているため、テーブルレベルの制約です。
無効な値を挿入してみてください:
INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate ) VALUES ( 1, 3, '2020-01-01', '1900-02-02' );
結果:
Msg 547, Level 16, State 0, Line 1 The INSERT statement conflicted with the CHECK constraint "chkValidEndDate". The conflict occurred in database "Test", table "dbo.ConstraintTest".
この制約をテストするには、チームメンバーを3に増やして、前の制約が最初にトリガーされないようにする必要があることに注意してください(CHECK
制約は、作成された順序で検証されます。
例4–チェック制約を変更する
CHECK
を実際に変更することはできません 制約。変更する必要がある場合は、削除して新しい定義で作成する必要があります。
例:
ALTER TABLE ConstraintTest DROP CONSTRAINT chkTeamSize; ALTER TABLE ConstraintTest ADD CONSTRAINT chkTeamSize CHECK (TeamSize >= 5 AND TeamSize <= 20) ;
前述のように、CHECK
制約は作成された順序で検証されるため、最初にキャッチされるエラーに影響を与える可能性があります。
したがって、この場合、無効な値を挿入しようとすると(また、無効な日付も含めると)、無効な日付が最初に検出されます:
INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate ) VALUES ( 1, 4, '2020-01-01', '1900-02-02' );
結果:
Msg 547, Level 16, State 0, Line 1 The INSERT statement conflicted with the CHECK constraint "chkValidEndDate". The conflict occurred in database "Test", table "dbo.ConstraintTest".
したがって、最新の制約を確認するには、最初に日付の問題を修正する必要があります:
INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate ) VALUES ( 1, 4, '2020-01-01', '2020-02-02' );
結果:
Msg 547, Level 16, State 0, Line 1 The INSERT statement conflicted with the CHECK constraint "chkTeamSize". The conflict occurred in database "Test", table "dbo.ConstraintTest", column 'TeamSize'.
したがって、私の最新の制約は期待どおりに機能しています。
例5–チェック制約とIDENTITY列
制約をテストしたので、先に進んで有効なデータを挿入しましょう:
INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate ) VALUES ( 1, 5, '2020-01-01', '2020-02-02' );
結果:
+--------------------+---------+------------+-------------+------------+ | ConstraintTestId | Price | TeamSize | StartDate | EndDate | |--------------------+---------+------------+-------------+------------| | 13 | 1.0000 | 5 | 2020-01-01 | 2020-02-02 | +--------------------+---------+------------+-------------+------------+
最後に、挿入が成功します。
ただし、IDENTITY
列はすでに13に増加しています。
最初にテーブルを作成したときに、ConstraintTestId
を定義したことを思い出してください。 IDENTITY(1,1)
を使用する列 、つまり、1から開始し、行が挿入されるたびに自動的に1ずつ増加する必要があります。
しかし、最終的に最初の行を挿入したので、値はすでに13になっています。これはIDENTITY
が原因です。 CHECK
の場合でも、列はインクリメントされます 制約により、INSERT
が発生します 失敗する操作。
この記事の例を考えているときに、いくつかの追加の失敗した挿入を行ったため、この記事をステップバイステップで実行した場合に得られる値よりも高い値に値が増加していることに注意してください。
>いずれにせよ、最後に失敗した挿入を1回実行してから、成功した挿入を実行してこれを確認しましょう。
挿入に失敗しました:
INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate ) VALUES ( 2, 4, '2020-01-02', '2020-02-03' );
結果:
Msg 547, Level 16, State 0, Line 1 The INSERT statement conflicted with the CHECK constraint "chkTeamSize". The conflict occurred in database "Test", table "dbo.ConstraintTest", column 'TeamSize'.
挿入の成功:
INSERT INTO ConstraintTest ( Price, TeamSize, StartDate, EndDate ) VALUES ( 2, 6, '2020-01-02', '2020-02-03' ); SELECT * FROM ConstraintTest;
結果:
+--------------------+---------+------------+-------------+------------+ | ConstraintTestId | Price | TeamSize | StartDate | EndDate | |--------------------+---------+------------+-------------+------------| | 13 | 1.0000 | 5 | 2020-01-01 | 2020-02-02 | | 15 | 2.0000 | 6 | 2020-01-02 | 2020-02-03 | +--------------------+---------+------------+-------------+------------+
IDENTITY
列は13から15にジャンプするため、挿入に失敗すると明らかに増加します。
CHECK制約のいくつかの制限
CHECK
を使用する際に注意すべきいくつかの制限があります 制約:
- 検索条件はブール式に評価される必要があり、別のテーブルを参照することはできません。
- 式にエイリアスデータ型を含めることはできません。
CHECK
テキストに制約を定義することはできません 、 ntext 、または画像 列。