Quando crei un CHECK
vincolo in SQL Server, potresti non pensare nemmeno se si tratti di un vincolo a livello di tabella o di un vincolo a livello di colonna.
Un CHECK
a livello di tabella vincolo si applica alla tabella, mentre un vincolo a livello di colonna si applica a una colonna specifica. Con un CHECK
a livello di tabella vincolo, è la riga che viene controllata quando controlla i dati. Con un CHECK
a livello di colonna vincolo, è la colonna specifica che viene selezionata.
Generalmente saprai se il vincolo che stai creando è un vincolo a livello di tabella o di colonna dalla definizione che gli dai. Se nell'espressione viene selezionata solo una colonna, sarà un vincolo a livello di colonna. Altrimenti sarà un vincolo a livello di tabella.
Ma come fai a sapere se i tuoi vincoli esistenti sono a livello di colonna o di tabella?
Puoi eseguire uno qualsiasi degli esempi di codice seguenti per determinare se i tuoi vincoli esistenti sono a livello di colonna o di tabella. Questi recuperano tutti i CHECK
vincoli per il database corrente, ma puoi sempre usare un WHERE
clausola per restringerla a un vincolo specifico.
Esempio 1 – Query di base
Ecco una semplice query che restituisce informazioni di base su tutti i CHECK
vincoli nel database corrente.
Qui, interrogo il sys.check_constraints
vista di sistema (che restituisce una riga per ogni oggetto che è un CHECK
vincolo, con sys.objects.type = 'C'
). Restituisco solo quattro colonne (ma sentiti libero di restituire tutte le colonne che desideri).
SELECT Name, OBJECT_NAME(parent_object_id) AS 'Table', parent_column_id, Definition FROM sys.check_constraints;
Risultato:
+-----------------+----------------+--------------------+----------------------------------------+ | 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') | +-----------------+----------------+--------------------+----------------------------------------+
Il modo più rapido per determinare quali vincoli sono vincoli a livello di tabella è cercare lo zero (
0
) in
parent_column_id
colonna. Qualsiasi cosa con uno zero è un CHECK
a livello di tabella vincolo. Un valore diverso da zero indica che si tratta di un CHECK
a livello di colonna vincolo definito sulla colonna con il valore ID specificato.
Quindi in questo esempio ci sono tre vincoli a livello di colonna e un vincolo a livello di tabella.
Nota che ci sono due vincoli con lo stesso parent_column_id (3), tuttavia, questi due vincoli provengono da tabelle diverse. Il 3 si riferisce alla terza colonna delle rispettive tabelle.
Come accennato, se vuoi solo informazioni su un vincolo specifico, usa un WHERE
clausola:
SELECT Name, OBJECT_NAME(parent_object_id) AS 'Table', parent_column_id, Definition FROM sys.check_constraints WHERE name = 'chkPrice';
Risultato:
+----------+----------------+--------------------+---------------+ | Name | Table | parent_column_id | Definition | |----------+----------------+--------------------+---------------| | chkPrice | ConstraintTest | 2 | ([Price]>(0)) | +----------+----------------+--------------------+---------------+
Esempio 2 – Migliora la query
Possiamo migliorare l'esempio precedente restituendo il nome della colonna padre anziché solo il suo ID. Ovviamente, questo restituirà il nome della colonna solo per i vincoli a livello di colonna. Per i vincoli a livello di tabella verrà restituito 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;
Risultato:
+-----------------+----------------+----------+----------------------------------------+ | 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') | +-----------------+----------------+----------+----------------------------------------+
Esempio 3 – Ulteriori miglioramenti
Modifichiamo ancora la query:
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;
Risultato:
+-----------------+-------------+----------------+----------------+----------+----------------------------------------+ | 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') | +-----------------+-------------+----------------+----------------+----------+----------------------------------------+
Quindi ora ho il testo "a livello di colonna" o "a livello di tabella", a seconda di quale sia.
Uso anche ISNULL()
funzione per trasformare qualsiasi valore NULL in "(n/a)".
E ho anche aggiunto is_disabled colonna all'elenco, nel caso in cui uno qualsiasi dei vincoli sia stato disabilitato. Puoi sempre dare a questa colonna lo stesso trattamento riservato a parent_column_id colonna e presentare "Sì" o "No" o "Abilitato" o "Disabilitato" o simili.