Når du opretter en CHECK
begrænsning i SQL Server, tænker du måske ikke engang over, om det er en begrænsning på tabelniveau eller en begrænsning på kolonneniveau.
En CHECK
på tabelniveau begrænsning gælder for tabellen, hvorimod en begrænsning på kolonneniveau gælder for en specifik kolonne. Med en CHECK
på tabelniveau begrænsning, det er rækken, der kontrolleres, når den tjekker dataene. Med en CHECK
på kolonneniveau begrænsning, det er den specifikke kolonne, der er markeret.
Generelt vil du vide, om den begrænsning, du opretter, er en begrænsning på tabelniveau eller kolonneniveau ifølge den definition, du giver den. Hvis kun én kolonne er markeret i udtrykket, vil det være en begrænsning på kolonneniveau. Ellers vil det være en begrænsning på tabelniveau.
Men hvordan ved du, om dine eksisterende begrænsninger er på kolonneniveau eller tabelniveau?
Du kan køre et hvilket som helst af kodeeksemplerne nedenfor for at bestemme, om dine eksisterende begrænsninger er på kolonneniveau eller tabelniveau. Disse henter alle CHECK
begrænsninger for den aktuelle database, men du kan altid bruge en WHERE
klausul for at indsnævre det til en specifik begrænsning.
Eksempel 1 – Grundlæggende forespørgsel
Her er en simpel forespørgsel, der returnerer grundlæggende oplysninger om alle CHECK
begrænsninger i den aktuelle database.
Her forespørger jeg sys.check_constraints
systemvisning (som returnerer en række for hvert objekt, der er en CHECK
begrænsning med sys.objects.type = 'C'
). Jeg returnerer kun fire kolonner (men du er velkommen til at returnere så mange kolonner, du vil).
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') | +-----------------+----------------+--------------------+----------------------------------------+
Den hurtigste måde at bestemme, hvilke begrænsninger der er begrænsninger på tabelniveau, er at kigge efter nullet (
0
) i
parent_column_id
kolonne. Alt med et nul er et CHECK
på tabelniveau begrænsning. En værdi, der ikke er nul, angiver, at det er en CHECK
på kolonneniveau begrænsning defineret i kolonnen med den angivne ID-værdi.
Så i dette eksempel er der tre begrænsninger på kolonneniveau og en begrænsning på tabelniveau.
Bemærk, at der er to begrænsninger med det samme parent_column_id (3), men disse to begrænsninger er fra forskellige tabeller. De 3 refererer til den tredje kolonne i deres respektive tabeller.
Som nævnt, hvis du kun ønsker information om en specifik begrænsning, skal du bruge 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)) | +----------+----------------+--------------------+---------------+
Eksempel 2 – Forbedre forespørgslen
Vi kan forbedre det forrige eksempel ved at returnere det overordnede kolonnenavn i stedet for kun dets ID. Dette vil naturligvis kun returnere kolonnenavnet for begrænsninger på kolonneniveau. For begrænsninger på tabelniveau vil NULL blive returneret.
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') | +-----------------+----------------+----------+----------------------------------------+
Eksempel 3 – Yderligere forbedringer
Lad os justere forespørgslen noget mere:
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å jeg får nu teksten "Kolonne-niveau" eller "Tabel-niveau" tilbage, afhængigt af hvilken det er.
Jeg bruger også ISNULL()
funktion til at omdanne eventuelle NULL-værdier til "(n/a)".
Og jeg har også tilføjet is_disabled kolonne til listen, bare hvis nogen af begrænsningerne er blevet deaktiveret. Du kan altid give denne kolonne samme behandling som parent_column_id kolonne og præsentere "Ja" eller "Nej" eller "Aktiveret" eller "Deaktiveret" eller lignende.