sql >> Databasteknik >  >> RDS >> Sqlserver

Ta reda på om en CHECK-begränsning är kolumnnivå eller tabellnivå i SQL Server (T-SQL-exempel)

När du skapar en CHECK begränsning i SQL Server kanske du inte ens tänker på om det är en begränsning på tabellnivå eller en begränsning på kolumnnivå.

En CHECK på tabellnivå begränsning gäller för tabellen, medan en begränsning på kolumnnivå gäller en specifik kolumn. Med en CHECK på tabellnivå begränsning, det är raden som kontrolleras när den kontrollerar data. Med en CHECK på kolumnnivå begränsning, det är den specifika kolumnen som är markerad.

I allmänhet vet du om begränsningen du skapar är en begränsning på tabellnivå eller kolumnnivå enligt den definition du ger den. Om endast en kolumn kontrolleras i uttrycket kommer det att vara en begränsning på kolumnnivå. Annars kommer det att vara en begränsning på tabellnivå.

Men hur vet du om dina befintliga begränsningar är kolumnnivå eller tabellnivå?

Du kan köra något av kodexemplen nedan för att avgöra om dina befintliga begränsningar är på kolumnnivå eller tabellnivå. Dessa hämtar alla CHECK begränsningar för den aktuella databasen, men du kan alltid använda en WHERE klausul för att begränsa den till en specifik begränsning.

Exempel 1 – Grundläggande fråga

Här är en enkel fråga som returnerar grundläggande information om alla CHECK begränsningar i den aktuella databasen.

Här frågar jag efter sys.check_constraints systemvy (som returnerar en rad för varje objekt som är en CHECK begränsning, med sys.objects.type = 'C' ). Jag returnerar bara fyra kolumner (men returnera gärna så många kolumner du vill).

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

Resultat:

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

Det snabbaste sättet att avgöra vilka begränsningar som är begränsningar på tabellnivå är att leta efter nollan ( 0 ) i parent_column_id kolumn. Allt med en nolla är en CHECK på tabellnivå begränsning. Ett värde som inte är noll anger att det är en CHECK på kolumnnivå begränsning definierad i kolumnen med det angivna ID-värdet.

Så i det här exemplet finns det tre begränsningar på kolumnnivå och en begränsning på tabellnivå.

Observera att det finns två begränsningar med samma parent_column_id (3), dock kommer dessa två begränsningar från olika tabeller. 3 hänvisar till den tredje kolumnen i deras respektive tabeller.

Som nämnts, om du bara vill ha information om en specifik begränsning, använd en WHERE klausul:

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

Resultat:

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

Exempel 2 – Förbättra frågan

Vi kan förbättra det föregående exemplet genom att returnera det överordnade kolumnnamnet istället för bara dess ID. Naturligtvis kommer detta att returnera kolumnnamnet endast för begränsningar på kolumnnivå. För begränsningar på tabellnivå kommer NULL att returneras.

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;

Resultat:

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

Exempel 3 – Ytterligare förbättringar

Låt oss justera frågan lite mer:

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;

Resultat:

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

Så jag har nu texten "Column-level" eller "Table-level" som returneras, beroende på vilken det är.

Jag använder också ISNULL() funktion för att omvandla alla NULL-värden till "(n/a)".

Och jag har också lagt till is_disabled kolumnen till listan, ifall någon av begränsningarna har inaktiverats. Du kan alltid ge denna kolumn samma behandling som parent_column_id kolumnen och presentera "Ja" eller "Nej" eller "Aktiverad" eller "Inaktiverad" eller liknande.


  1. Ska jag använda datatypen datetime eller timestamp i MySQL?

  2. Introduktion till Amazon Web Services (AWS) automatisk skalning

  3. Vad är bättre för din big data-applikation, SQL eller NoSQL?

  4. En berättelse om två klustringsfaktorer