Unique 制約と check 制約

適用対象:SQL ServerAzure SQL DatabaseAzure SQL Managed Instance

UNIQUE 制約と CHECK 制約は、SQL Server テーブル内でデータの整合性を確保するために使用できる 2 種類の制約です。 これらは重要なデータベース オブジェクトです。

この記事には、次のセクションがあります。

UNIQUE 制約

制約とは、SQL Server データベース エンジンによって適用される規則です。 たとえば、UNIQUE 制約を使用して、主キーに関係しない特定の列に重複した値が入力されないようにできます。 UNIQUE 制約も PRIMARY KEY 制約も一意性を設定しますが、主キーではない列または列セットに一意性を設定する場合は、UNIQUE 制約ではなく PRIMARY KEY 制約を使用します。

PRIMARY KEY 制約とは異なり、UNIQUE 制約は NULL 値を許容できます。 ただし、UNIQUE 制約が適用される他の値と同様に、NULL 値も 1 列に 1 つしか使用できません。 UNIQUE 制約は FOREIGN KEY KEY 制約から参照することもできます。

既定では、テーブルの既存の列に UNIQUE 制約を追加すると、すべての値が一意であることを確認するために、データベース エンジンにより列の既存のデータが調べられます。 重複した値を含む列に UNIQUE 制約を追加すると、データベース エンジンによりエラーが返され、制約は追加されません。

データベース エンジンは、UNIQUE 制約による一意性の要件を強制する UNIQUE インデックスを自動的に作成します。 このため、重複した行を挿入しようとすると、UNIQUE 制約に違反していることを示すエラー メッセージがデータベース エンジンにより返され、テーブルには行が追加されません。 クラスター化インデックスが明示的に指定されていない限り、UNIQUE 制約を強制する一意の非クラスター化インデックスが既定で作成されます。

CHECK 制約

CHECK 制約は、1 つ以上の列に格納できる値を制限することによってドメインの整合性を強制します。 論理演算子に基づいて CHECK または TRUE を返す論理 (ブール) 式を使って FALSE 制約を作成できます。 たとえば、salary 列の値の範囲は、$15,000 ~ $100,000 のデータのみを許容する CHECK 制約を作成することにより制限できます。 これにより、この一定の給与範囲を超える給与を入力できなくなります。 論理式は、 salary >= 15000 AND salary <= 100000になります。

複数の CHECK 制約を 1 つの列に適用できます。 テーブル レベルで CHECK 制約を作成することで、1 つの制約を複数の列に適用できます。 たとえば、複数列の CHECK 制約を使用して、country_region 列の値が USA であるいずれかの行の state 列に 2 文字の値が格納されているかどうかを確認できます。 これにより、1 か所で複数の条件をチェックできるようになります。

CHECK 制約は、列に格納される値を制御するという点では FOREIGN KEY 制約に似ています。 異なる点は、有効な値を決定する方法です。FOREIGN KEY 制約では別のテーブルから有効な値の一覧が取得されますが、CHECK 制約では論理式によって有効な値が決定されます。

注意

暗黙的または明示的なデータ型の変換が含まれる制約により、特定の操作が失敗することがあります。 たとえば、パーティションの切り替え元のテーブルに定義された制約により、ALTER TABLE...SWITCH 操作が失敗することがあります。 制約の定義ではデータ型を変換しないようにしてください。

CHECK 制約の制限事項

CHECK 制約は、FALSE と評価された値を拒否します。 NULL 値は UNKNOWN と評価されるので、式に NULL 値が含まれていると制約がオーバーライドされる場合があります。 たとえば、int 型の列 MyColumn に、MyColumn には値 10 (MyColumn=10) しか格納できないことを指定する制約を適用したとします。 NULLMyColumn 値を挿入すると、データベース エンジンによって NULL が挿入され、エラーは返されません。

CHECK 制約は、チェックしている条件がテーブルのすべての行に対して TRUE でない場合、FALSE を返します。 CHECK 制約は行レベルで機能します。 作成したばかりのテーブルに行が含まれていない場合、このテーブルに適用された CHECK 制約は有効であると見なされます。 この場合、次の例に示すような予期しない結果が生成されることがあります。

CREATE TABLE CheckTbl (col1 INT, col2 INT);
GO

CREATE FUNCTION CheckFnctn()
RETURNS INT
AS
BEGIN
    DECLARE @retval INT;
    SELECT @retval = COUNT(*)
    FROM CheckTbl;

    RETURN @retval;
END;
GO

ALTER TABLE CheckTbl ADD CONSTRAINT chkRowCount CHECK (dbo.CheckFnctn() >= 1);
GO

追加する CHECK 制約では、テーブル CheckTblに 1 行以上の行が格納されていなければならないことを指定します。 ただし、テーブルにはこの制約の条件をチェックする行が存在しないので、ALTER TABLE ステートメントは成功します。

CHECK 制約は、DELETE ステートメント中に検証されません。 そのため、特定の種類の CHECK 制約が適用されたテーブルで DELETE ステートメントを実行すると、予期しない結果が生成されることがあります。 たとえば、テーブル CheckTblで次のステートメントを実行するとします。

INSERT INTO CheckTbl VALUES (10, 10);
GO
DELETE CheckTbl WHERE col1 = 10;

CHECK 制約では、テーブル CheckTbl1 行以上が格納されていなければならないことを指定していますが、DELETE ステートメントは成功します。

Note

テーブルをレプリケーションのためにパブリッシュする場合は、Transact-SQL ステートメントの ALTER TABLE または SQL Server 管理オブジェクト (SMO) を使用してスキーマを変更する必要があります。 テーブル デザイナーまたはデータベース ダイアグラム デザイナーを使用してスキーマを変更するとき、テーブルはいったん削除されてから再作成されます。 パブリッシュされたオブジェクトは削除できないので、スキーマの変更は失敗します。

タスク 記事
UNIQUE 制約の作成方法について説明します。 UNIQUE 制約の作成
UNIQUE 制約の変更方法について説明します。 UNIQUE 制約の変更
UNIQUE 制約の削除方法について説明します。 UNIQUE 制約の削除
CHECK 制約の作成方法について説明します。 CHECK 制約の作成
レプリケーション エージェントによってテーブルのデータが挿入または更新された場合に CHECK 制約を無効にする方法について説明します。 レプリケーションの CHECK 制約の無効化
テーブルに対してデータの追加、更新、または削除を行う際に、CHECK 制約を無効にする方法について説明します。 INSERT ステートメントまたは UPDATE ステートメントによる CHECK 制約の無効化
制約式を変更するか、または特定条件の制約を有効または無効にするオプションを変更する方法について説明します。 CHECK 制約の変更
CHECK 制約の削除方法について説明します。 CHECK 制約の削除
CHECK 制約のプロパティを表示する方法について説明します。 UNIQUE 制約と CHECK 制約