Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Herausfinden, ob eine CHECK-Einschränkung in SQL Server auf Spalten- oder Tabellenebene liegt (T-SQL-Beispiele)

Wenn Sie einen CHECK erstellen Einschränkung in SQL Server, denken Sie vielleicht nicht einmal darüber nach, ob es sich um eine Einschränkung auf Tabellenebene oder eine Einschränkung auf Spaltenebene handelt.

Ein CHECK auf Tabellenebene Einschränkung gilt für die Tabelle, während eine Einschränkung auf Spaltenebene für eine bestimmte Spalte gilt. Mit einem CHECK auf Tabellenebene Einschränkung, es ist die Zeile, die überprüft wird, wenn die Daten überprüft werden. Mit einem CHECK auf Spaltenebene Einschränkung, es ist die spezifische Spalte, die überprüft wird.

Im Allgemeinen wissen Sie anhand der Definition, die Sie ihr geben, ob die Einschränkung, die Sie erstellen, eine Einschränkung auf Tabellen- oder Spaltenebene ist. Wenn nur eine Spalte im Ausdruck überprüft wird, handelt es sich um eine Einschränkung auf Spaltenebene. Andernfalls handelt es sich um eine Einschränkung auf Tabellenebene.

Aber woher wissen Sie, ob Ihre bestehenden Einschränkungen auf Spalten- oder Tabellenebene liegen?

Sie können eines der folgenden Codebeispiele ausführen, um zu bestimmen, ob Ihre vorhandenen Einschränkungen auf Spalten- oder Tabellenebene liegen. Diese rufen alle CHECK ab Einschränkungen für die aktuelle Datenbank, aber Sie können immer ein WHERE verwenden -Klausel, um sie auf eine bestimmte Einschränkung einzugrenzen.

Beispiel 1 – Grundlegende Abfrage

Hier ist eine einfache Abfrage, die grundlegende Informationen über alle CHECK zurückgibt Beschränkungen in der aktuellen Datenbank.

Hier frage ich die sys.check_constraints ab Systemansicht (die eine Zeile für jedes Objekt zurückgibt, das ein CHECK ist Einschränkung, mit sys.objects.type = 'C' ). Ich gebe nur vier Spalten zurück (aber Sie können so viele Spalten zurückgeben, wie Sie möchten).

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

Ergebnis:

+-----------------+----------------+--------------------+----------------------------------------+
| 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')          |
+-----------------+----------------+--------------------+----------------------------------------+

Der schnellste Weg, um zu bestimmen, welche Einschränkungen Einschränkungen auf Tabellenebene sind, besteht darin, nach der Null zu suchen ( 0 ) in der parent_column_id Säule. Alles mit einer Null ist ein CHECK auf Tabellenebene Zwang. Ein Wert ungleich Null zeigt an, dass es sich um einen CHECK auf Spaltenebene handelt Einschränkung, die für die Spalte mit dem angegebenen ID-Wert definiert ist.

In diesem Beispiel gibt es also drei Einschränkungen auf Spaltenebene und eine Einschränkung auf Tabellenebene.

Beachten Sie, dass es zwei Einschränkungen mit derselben parent_column_id gibt (3), diese beiden Einschränkungen stammen jedoch aus unterschiedlichen Tabellen. Die 3 bezieht sich auf die dritte Spalte ihrer jeweiligen Tabellen.

Wie bereits erwähnt, wenn Sie nur Informationen zu einer bestimmten Einschränkung wünschen, verwenden Sie ein WHERE Klausel:

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

Ergebnis:

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

Beispiel 2 – Verbessern Sie die Abfrage

Wir können das vorherige Beispiel verbessern, indem wir den Namen der übergeordneten Spalte zurückgeben, anstatt nur ihre ID. Dies gibt natürlich nur den Spaltennamen für Einschränkungen auf Spaltenebene zurück. Für Einschränkungen auf Tabellenebene wird NULL zurückgegeben.

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;

Ergebnis:

+-----------------+----------------+----------+----------------------------------------+
| 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')          |
+-----------------+----------------+----------+----------------------------------------+

Beispiel 3 – Weitere Verbesserungen

Lassen Sie uns die Abfrage noch etwas optimieren:

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;

Ergebnis:

+-----------------+-------------+----------------+----------------+----------+----------------------------------------+
| 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')          |
+-----------------+-------------+----------------+----------------+----------+----------------------------------------+

Ich habe also jetzt den Text „Spaltenebene“ oder „Tabellenebene“ zurückgegeben, je nachdem, um welche es sich handelt.

Ich verwende auch ISNULL() Funktion, um alle NULL-Werte in „(n/a)“ umzuwandeln.

Und ich habe auch is_disabled hinzugefügt Spalte in die Liste, nur für den Fall, dass eine der Einschränkungen deaktiviert wurde. Sie könnten dieser Spalte immer die gleiche Behandlung zuweisen wie der parent_column_id Spalte und zeigen Sie „Ja“ oder „Nein“ oder „Aktiviert“ oder „Deaktiviert“ oder ähnliches an.