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

SQL ServerでCHECK制約が列レベルかテーブルレベルかを確認します(T-SQLの例)

    CHECKを作成するとき SQL Serverの制約では、それがテーブルレベルの制約なのか列レベルの制約なのかさえ考えられないかもしれません。

    テーブルレベルのCHECK 制約はテーブルに適用されますが、列レベルの制約は特定の列に適用されます。テーブルレベルのCHECK 制約、データをチェックするときにチェックされるのは行です。列レベルのCHECK 制約、チェックされるのは特定の列です。

    一般に、作成する制約がテーブルレベルまたは列レベルの制約であるかどうかは、指定する定義によってわかります。式でチェックされている列が1つだけの場合、それは列レベルの制約になります。それ以外の場合は、テーブルレベルの制約になります。

    しかし、既存の制約が列レベルかテーブルレベルかをどうやって知るのでしょうか?

    以下のコード例のいずれかを実行して、既存の制約が列レベルかテーブルレベルかを判断できます。これらはすべてのCHECKを取得します 現在のデータベースの制約ですが、いつでもWHEREを使用できます 特定の制約に絞り込むための句。

    例1-基本的なクエリ

    これは、すべてのCHECKに関する基本情報を返す簡単なクエリです。 現在のデータベースの制約。

    ここでは、sys.check_constraintsにクエリを実行します システムビュー(CHECKである各オブジェクトの行を返します 制約、sys.objects.type = 'C' )。返す列は4つだけです(ただし、好きなだけ列を返すことができます)。

    SELECT 
      Name,
      OBJECT_NAME(parent_object_id) AS 'Table',
      parent_column_id,
      Definition
    FROM sys.check_constraints;
    

    結果:

    +-----------------+----------------+--------------------+----------------------------------------+
    | Name            | Table          | parent_column_id   | Definition                             |
    |-----------------+----------------+--------------------+----------------------------------------|
    | chkPrice        | ConstraintTest | 2                  | ([Price]>(0))                          |
    | chkValidEndDate | ConstraintTest | 0                  | ([EndDate]>=[StartDate])               |
    | chkTeamSize     | ConstraintTest | 3                  | ([TeamSize]>=(5) AND [TeamSize]<=(20)) |
    | chkJobTitle     | Occupation     | 3                  | ([JobTitle]<>'Digital Nomad')          |
    +-----------------+----------------+--------------------+----------------------------------------+
    

    どの制約がテーブルレベルの制約であるかを判断する最も簡単な方法は、ゼロ( 0 )を探すことです。 ) parent_column_id 内 桁。ゼロのあるものはすべて、テーブルレベルのCHECKです。 制約。ゼロ以外の値は、それが列レベルのCHECKであることを示します 指定されたID値を持つ列に定義された制約。

    したがって、この例では、3つの列レベルの制約と1つのテーブルレベルの制約があります。

    同じ parent_column_id には2つの制約があることに注意してください (3)ただし、これら2つの制約は異なるテーブルからのものです。 3は、それぞれのテーブルの3番目の列を示します。

    前述のように、特定の制約に関する情報のみが必要な場合は、WHEREを使用してください 条項:

    SELECT 
      Name,
      OBJECT_NAME(parent_object_id) AS 'Table',
      parent_column_id,
      Definition
    FROM sys.check_constraints
    WHERE name = 'chkPrice';
    

    結果:

    +----------+----------------+--------------------+---------------+
    | Name     | Table          | parent_column_id   | Definition    |
    |----------+----------------+--------------------+---------------|
    | chkPrice | ConstraintTest | 2                  | ([Price]>(0)) |
    +----------+----------------+--------------------+---------------+
    

    例2–クエリを改善する

    IDだけでなく親列名を返すことで、前の例を改善できます。もちろん、これは列レベルの制約の列名のみを返します。テーブルレベルの制約の場合、NULLが返されます。

    SELECT 
      cc.name AS 'Constraint',
      o.name AS 'Table',
      ac.name AS 'Column',
      cc.Definition AS 'Constraint Definition'
    FROM sys.check_constraints cc
    LEFT OUTER JOIN sys.objects o
      ON cc.parent_object_id = o.object_id
    LEFT OUTER JOIN sys.all_columns ac
      ON cc.parent_column_id = ac.column_id
      AND cc.parent_object_id = ac.object_id;
    

    結果:

    +-----------------+----------------+----------+----------------------------------------+
    | Constraint      | Table          | Column   | Constraint Definition                  |
    |-----------------+----------------+----------+----------------------------------------|
    | chkPrice        | ConstraintTest | Price    | ([Price]>(0))                          |
    | chkValidEndDate | ConstraintTest | NULL     | ([EndDate]>=[StartDate])               |
    | chkTeamSize     | ConstraintTest | TeamSize | ([TeamSize]>=(5) AND [TeamSize]<=(20)) |
    | chkJobTitle     | Occupation     | JobTitle | ([JobTitle]<>'Digital Nomad')          |
    +-----------------+----------------+----------+----------------------------------------+
    

    例3–さらなる改善

    クエリをもう少し微調整しましょう:

    SELECT 
      cc.name AS 'Constraint',
      cc.is_disabled AS 'Disabled?',
      CASE WHEN cc.parent_column_id = 0
        THEN 'Table-level'
        ELSE 'Column-level'
        END AS 'Table/Column',
      o.name AS 'Table',
      ISNULL(ac.name, '(n/a)') AS 'Column',
      cc.Definition AS 'Constraint Definition'
    FROM sys.check_constraints cc
    LEFT OUTER JOIN sys.objects o
      ON cc.parent_object_id = o.object_id
    LEFT OUTER JOIN sys.all_columns ac
      ON cc.parent_column_id = ac.column_id
      AND cc.parent_object_id = ac.object_id;
    

    結果:

    +-----------------+-------------+----------------+----------------+----------+----------------------------------------+
    | Constraint      | Disabled?   | Table/Column   | Table          | Column   | Constraint Definition                  |
    |-----------------+-------------+----------------+----------------+----------+----------------------------------------|
    | chkPrice        | 0           | Column-level   | ConstraintTest | Price    | ([Price]>(0))                          |
    | chkValidEndDate | 0           | Table-level    | ConstraintTest | (n/a)    | ([EndDate]>=[StartDate])               |
    | chkTeamSize     | 0           | Column-level   | ConstraintTest | TeamSize | ([TeamSize]>=(5) AND [TeamSize]<=(20)) |
    | chkJobTitle     | 0           | Column-level   | Occupation     | JobTitle | ([JobTitle]<>'Digital Nomad')          |
    +-----------------+-------------+----------------+----------------+----------+----------------------------------------+
    

    そのため、どちらかによって、「列レベル」または「テーブルレベル」というテキストが返されます。

    ISNULL()も使用します NULL値を「(n / a)」に変換する関数。

    また、 is_disabled も追加しました いずれかの制約が無効になっている場合に備えて、列をリストに追加します。この列には、常に parent_column_id と同じ扱いをすることができます。 列に「はい」、「いいえ」、「有効」、「無効」などを表示します。


    1. MySQLでタイムゾーンを変換する方法

    2. rewriteBatchedStatements=trueを使用したMySQLおよびJDBC

    3. MySQLで列の名前を変更中にエラーが発生しました

    4. HibernateのScrollableResultsを使用して9千万件のレコードをゆっくりと読み取る