sql >> データベース >  >> RDS >> Sqlserver

SQL ServerでCHECK制約を作成する方法(T-SQLの例)

    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 、または画像 列。

    1. Oracle FORLOOPSELECTステートメントの例

    2. 追加の(個別の)フィルターを使用して列を集約します

    3. PDO AdvancedCRUDGeneratorツールを使用してPHPCRUDインターフェイスをすばやく構築する

    4. Windowsxamppでlower_case_table_names=2の値を変更する場所