Kiedy tworzysz CHECK
ograniczenia w SQL Server, możesz nawet nie myśleć o tym, czy jest to ograniczenie na poziomie tabeli, czy na poziomie kolumny.
CHECK
na poziomie tabeli ograniczenie dotyczy tabeli, podczas gdy ograniczenie na poziomie kolumny dotyczy określonej kolumny. Z CHECK
na poziomie tabeli ograniczenie, jest to wiersz, który jest sprawdzany podczas sprawdzania danych. Za pomocą kolumny CHECK
na poziomie kolumny ograniczenie, zaznaczona jest konkretna kolumna.
Generalnie będziesz wiedzieć, czy ograniczenie, które tworzysz, jest ograniczeniem na poziomie tabeli, czy na poziomie kolumny, dzięki podanej przez Ciebie definicji. Jeśli w wyrażeniu jest sprawdzana tylko jedna kolumna, będzie to ograniczenie na poziomie kolumny. W przeciwnym razie będzie to ograniczenie na poziomie tabeli.
Ale skąd wiesz, czy istniejące ograniczenia są na poziomie kolumny czy tabeli?
Możesz uruchomić dowolny z poniższych przykładów kodu, aby określić, czy istniejące ograniczenia są na poziomie kolumny czy tabeli. Pobierają one wszystkie CHECK
ograniczenia dla bieżącej bazy danych, ale zawsze możesz użyć WHERE
klauzulę, aby zawęzić ją do konkretnego ograniczenia.
Przykład 1 – zapytanie podstawowe
Oto proste zapytanie, które zwraca podstawowe informacje o wszystkich CHECK
ograniczenia w bieżącej bazie danych.
Tutaj pytam o sys.check_constraints
widok systemowy (który zwraca wiersz dla każdego obiektu będącego CHECK
ograniczenie, z sys.objects.type = 'C'
). Zwracam tylko cztery kolumny (ale możesz zwrócić tyle kolumn, ile chcesz).
SELECT Name, OBJECT_NAME(parent_object_id) AS 'Table', parent_column_id, Definition FROM sys.check_constraints;
Wynik:
+-----------------+----------------+--------------------+----------------------------------------+ | 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') | +-----------------+----------------+--------------------+----------------------------------------+
Najszybszym sposobem określenia, które ograniczenia są ograniczeniami na poziomie tabeli, jest szukanie zera (
0
) w
parent_column_id
kolumna. Wszystko, co ma zero, to CHECK
na poziomie tabeli ograniczenie. Wartość niezerowa wskazuje, że jest to CHECK
na poziomie kolumny ograniczenie zdefiniowane w kolumnie o określonej wartości identyfikatora.
W tym przykładzie występują trzy ograniczenia na poziomie kolumny i jedno ograniczenie na poziomie tabeli.
Zwróć uwagę, że istnieją dwa ograniczenia z tym samym parent_column_id (3) jednak te dwa ograniczenia pochodzą z różnych tabel. 3 odnosi się do trzeciej kolumny odpowiednich tabel.
Jak wspomniano, jeśli chcesz uzyskać informacje tylko o określonym ograniczeniu, użyj WHERE
klauzula:
SELECT Name, OBJECT_NAME(parent_object_id) AS 'Table', parent_column_id, Definition FROM sys.check_constraints WHERE name = 'chkPrice';
Wynik:
+----------+----------------+--------------------+---------------+ | Name | Table | parent_column_id | Definition | |----------+----------------+--------------------+---------------| | chkPrice | ConstraintTest | 2 | ([Price]>(0)) | +----------+----------------+--------------------+---------------+
Przykład 2 – Ulepsz zapytanie
Możemy poprawić poprzedni przykład, zwracając nazwę kolumny nadrzędnej zamiast samego jej identyfikatora. Oczywiście zwróci to nazwę kolumny tylko dla ograniczeń na poziomie kolumny. W przypadku ograniczeń na poziomie tabeli zostanie zwrócone 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;
Wynik:
+-----------------+----------------+----------+----------------------------------------+ | 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') | +-----------------+----------------+----------+----------------------------------------+
Przykład 3 – Dalsze ulepszenia
Dostosujmy zapytanie jeszcze bardziej:
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;
Wynik:
+-----------------+-------------+----------------+----------------+----------+----------------------------------------+ | 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') | +-----------------+-------------+----------------+----------------+----------+----------------------------------------+
Tak więc mam teraz zwracany tekst „Poziom kolumny” lub „Poziom tabeli”, w zależności od tego, który to jest.
Używam również ISNULL()
funkcja zmieniająca dowolne wartości NULL na „(nie dotyczy)”.
Dodałem również is_disabled kolumny do listy, na wypadek gdyby którekolwiek z ograniczeń zostało wyłączone. Zawsze możesz potraktować tę kolumnę tak samo jak parent_column_id kolumnę i przedstawić „Tak” lub „Nie” lub „Włączone” lub „Wyłączone” lub podobne.