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.