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

SQLServerのチェック制約

    この記事では、CHECK制約について説明します。 SQL Serverテーブルの列にCHECK制約を追加する方法を確認し、このタイプのSQLServer制約を使用するときに発生する可能性のある落とし穴について説明します。

    チェック制約の基本

    CHECK制約は、データの整合性を維持するためにテーブル列を参照する単なる条件ステートメント(TRUEまたはFALSEを返す述語)です。 1つの行の1つまたは複数の列にデータを挿入すると、CHECK制約が実行されます。挿入するデータを評価します。データがCHECK制約で指定された条件を満たさない場合、挿入は失敗します。

    次の例を検討してください。

    給与列に制限を設定して、$150,000を超えない正の値のみを格納するようにする必要があります。条件文は次のようになります:(給与>=0および給与 <=150000)。負の値を挿入しようとすると、述語はFALSEになり、挿入は失敗します。

    単一または複数の列にCHECK制約を追加することができます。複数列のCHECK制約の追加は、テーブルレベルで実装できます。

    CHECK制約の操作

    SSMSでチェック制約を作成する方法

    1. オブジェクトエクスプローラー 、必要なテーブルに移動します。

    2. 制約を右クリックします フォルダを選択してからc 新しい制約をなめる…

    3. チェック制約の右側のペイン ダイアログボックスで、をクリックします 次に、省略記号ボタンをクリックします。

    1. CHECK制約式をチェック制約式のテキストフィールドに入力します ダイアログボックス。たとえば、Zip列に7桁の郵便番号のみを許可するには、式は次のようになります。

    テーブルデザイナ セクションでは、制約を適用するためのルールを設定できます。

    CREATETABLEのチェック制約

    次の例を検討してください。

    銀行の顧客に関するデータを格納するテーブルを作成し、テストデータを入力する必要があります。この表には、顧客ID、名、姓、ステータス、電話、市、州、郵便番号の列が含まれます。

    テーブルを作成するときは、次の事実を考慮する必要があります。

    1. 基本的なZIP形式は5桁の数字で構成されています。

    2. 標準のアメリカの電話番号は10桁で、(555)555-1234

      のようになります。
    3. 2文字の略語は、住所、データ処理、一般的な略語、およびその他の目的で米国の政治的区分を表すために使用されます。

    タスクは、テーブルにデータの一貫性を提供することです。 12桁の電話番号や6桁のzipなどの挿入を禁止する必要があります。これを行うために、SQLServerではテーブル列ごとに1つ以上のCHECK制約を追加できます。

    前のセクションでは、SSMSでCHECK制約を作成する1つの方法を検討しました。次に、T-SQLを使用して制約を作成する方法について説明します。

    次のスクリプトは、Zip列にCHECK制約を作成する方法を示しています。

    CREATE TABLE Customers
    (
     Customer_Id tinyint NOT NULL,
     [First Name] varchar(50),
     [Last Name] varchar(50),
     Status varchar(50),
     Phone tinyint,
     Address varchar(50),
     State varchar(50),
     Zip tinyint,
     Email varchar(50),
     [Credit Limit] INT NULL,
     CONSTRAINT CK_Zip CHECK (Zip LIKE REPLICATE ('[0-9]', 5)) --Check Constraint Condition
    )

    では、6桁の値をZip列に挿入しようとすると何が得られるかを見てみましょう。

    INSERT INTO dbo.Customers (Customer_Id, [First Name], [Last Name], Status, Phone, Address, State, Zip, Email)
    SELECT 1, 'James', 'Madison', 'Mr', 555-555-1234, 'Madison street, 12', 'LA', 123456, NULL
    GO

    挿入が失敗し、SQLServerは次の防止策を表示します。

    これまでのところ、とても良いです。

    CHECK制約のCASE式

    銀行には、ルイジアナ州の居住者のクレジット制限を150,000ドル未満に設定するビジネスルールがあると想定します。この要件を実装するには、[クレジット制限]列にCHECK制約を追加します。

    ALTER TABLE dbo.Customers
    ADD CONSTRAINT CK_Credit_Limit
    CHECK (State='LA' AND [Credit Limit] <= 150000)
    GO
    
    INSERT INTO Customers (Customer_Id, Name, Status, Phone, State, Zip, Email, [Credit Limit])
    VALUES (1, 'James Black', 'Mr', 5558787, 'LA', 46853, '[email protected]', 120000);
    GO
    
    INSERT INTO Customers (Customer_Id, Name, Status, Phone, State, Zip, Email, [Credit Limit])
    VALUES (2, 'Mark Spencer', 'Mr', 3332244, 'NY', 23487, '[email protected]', 200000);
    GO

    上記のステートメントを実行すると、次のエラーが発生します。

    INSERTステートメントがCHECK制約と競合しました。何が悪かったのですか?

    クエリを詳しく見てみましょう。 CHECK制約では、State列の「LA」値のみが許可されることに注意してください。同時に、[クレジット]列の値は150000を超えてはなりません。

    同様に、CHECK制約では、列に他の状態コードを書き込むことはできません。

    したがって、条件を変更する必要があります。ビジネスロジックによると、銀行はルイジアナ州の住民に150000ドルのクレジット制限を提供します。同時に、この値は他の居住者によって異なる場合があります。

    このケースを実装するには、CHECK制約内でCASE句を使用します:

    ALTER TABLE dbo.Customers
    ADD CONSTRAINT CK_Credit_Limit
    CHECK (CASE WHEN State='LA' AND [Credit Limit] <= 150000 THEN 1 ELSE 0 END = 1)
    GO

    この表現はビジネスロジックを完全に満たしています。

    CHECK制約のNULL値

    銀行は顧客をセグメントに分割します。 [ステータス]列には、クライアントがVIPであるか通常であるかを判断するデータが含まれています。常連客のクレジット限度額の上限は$200,000です。 VIPは$500,000を利用できます。

    CHECK制約は次のようになります。

    ALTER TABLE dbo.Customers
    ADD CONSTRAINT CK_Status_Credit_Limit
    CHECK (Status = 'VIP' OR Status = 'Regular')
    GO

    CHECK制約では、State列にNULLを挿入できることに注意してください(明示的に定義されたNOT NULL制約がない場合)。 CHECK制約は値を評価し、TRUEまたはFALSEを返します。 NULLをUNKNOWNと評価します。したがって、NULLはエラーを引き起こしません。これは、SELECTまたはUPDATEステートメントのWHERE句の述語とは対照的です。

    チェックとノーチェック

    時々、ビジネスロジックは変化します。データベースオブジェクトが変更されます。国が郵便番号ベースを拡張し、6桁の値を追加するとします。

    古い5桁の値はエリアに割り当てられなくなります。ただし、既存のものには引き続き有効です。したがって、CHECK制約は、古い形式の既存のデータを考慮に入れ、新しい形式のデータを検証する必要があります。

    NOCHECK句はこの問題を解決します:

    ALTER TABLE Customers WITH NOCHECK
    ADD CONSTRAINT CK_Zip_Code
    CHECK (Zip LIKE REPLICATE('[0-9]', 6));
    GO

    次の挿入は成功しました:

    INSERT INTO Customers (Customer_Id, Name, Status, Phone, State, Zip, Email, [Credit Limit])
    VALUES (102, 'Jake Harrison', 'VIP', 555-555-1234, 'NY', 123456, '[email protected]', 100000);
    GO

    5桁のzipを挿入しようとすると、エンジンはエラーをスローします:

    DBCC CHECKCONSTRAINTS

    SQL Serverは、制約に一致しないデータを検索するためのDBCCCHECKCONSTRAINTSを提供します。

    データベースの整合性に問題がある場合は、データベース全体に対してDBCC CHECKCONSTRAINTSを実行して、問題がないことを確認してください。

    このコマンドはパフォーマンスに影響することに注意してください。したがって、スケジュールどおりに実行しないでください。

    単一の制約、テーブル、またはデータベース全体に対してDBCCCHECKCONSTRAINTSを実行することができます。

    他のチェックコマンドと比較すると、DBCC CHECKCONSTRAINTSは完了するのにかなりの時間がかかり、システムリソースを消費します。他のコマンドとは異なり、CHECKCONSTRAINTSはデータベーススナップショットを利用しません。

    結論

    CHECK制約は、挿入前にデータを評価するためのメカニズムを提供します。 CHECK制約は、単一の列または複数のテーブル列を参照できます。

    制約は、TRUE、FALSE、またはUNKNOWNになる述語です。 NULLがテーブルに挿入された場合、制約に違反しません。


    1. COUNTSQL関数のパフォーマンス

    2. MySQLでDATETIMEからDATEとTIMEを分離する方法

    3. 外部キーをNULLにしたり、重複させたりすることはできますか?

    4. Oracle-読み取り専用ユーザーを作成する方法