Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Descubra se uma restrição CHECK é no nível da coluna ou no nível da tabela no SQL Server (Exemplos de T-SQL)


Quando você cria um CHECK restrição no SQL Server, você pode nem pensar se é uma restrição de nível de tabela ou uma restrição de nível de coluna.

Um CHECK no nível da tabela restrição se aplica à tabela, enquanto uma restrição de nível de coluna se aplica a uma coluna específica. Com um CHECK no nível da tabela restrição, é a linha que é verificada quando verifica os dados. Com um CHECK no nível da coluna restrição, é a coluna específica que é verificada.

Geralmente, você saberá se a restrição que está criando é uma restrição de nível de tabela ou de coluna pela definição que você der. Se apenas uma coluna estiver sendo verificada na expressão, será uma restrição de nível de coluna. Caso contrário, será uma restrição de nível de tabela.

Mas como você sabe se suas restrições existentes são em nível de coluna ou em nível de tabela?

Você pode executar qualquer um dos exemplos de código abaixo para determinar se suas restrições existentes são em nível de coluna ou em nível de tabela. Estes recuperam todos os CHECK restrições para o banco de dados atual, mas você sempre pode usar um WHERE cláusula para reduzi-lo a uma restrição específica.


Exemplo 1 – Consulta básica


Aqui está uma consulta simples que retorna informações básicas sobre todos os CHECK restrições no banco de dados atual.

Aqui, eu consulto as sys.check_constraints visão do sistema (que retorna uma linha para cada objeto que é um CHECK restrição, com sys.objects.type = 'C' ). Eu só retorno quatro colunas (mas sinta-se à vontade para retornar quantas colunas quiser).
SELECT 
  Name,
  OBJECT_NAME(parent_object_id) AS 'Table',
  parent_column_id,
  Definition
FROM sys.check_constraints;

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

A maneira mais rápida de determinar quais restrições são restrições de nível de tabela é procurar o zero ( 0 ) no parent_column_id coluna. Qualquer coisa com zero é um CHECK no nível da tabela limitação. Um valor diferente de zero indica que é um CHECK no nível da coluna restrição definida na coluna com o valor de ID especificado.

Portanto, neste exemplo, há três restrições em nível de coluna e uma restrição em nível de tabela.

Observe que há duas restrições com o mesmo parent_column_id (3), no entanto, essas duas restrições são de tabelas diferentes. O 3 refere-se à terceira coluna de suas respectivas tabelas.

Como mencionado, se você deseja apenas informações sobre uma restrição específica, use um WHERE cláusula:
SELECT 
  Name,
  OBJECT_NAME(parent_object_id) AS 'Table',
  parent_column_id,
  Definition
FROM sys.check_constraints
WHERE name = 'chkPrice';

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

Exemplo 2 – Melhorar a consulta


Podemos melhorar o exemplo anterior retornando o nome da coluna pai em vez de apenas seu ID. Obviamente, isso retornará o nome da coluna apenas para restrições de nível de coluna. Para restrições de nível de tabela, NULL será retornado.
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;

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

Exemplo 3 – Melhorias adicionais


Vamos ajustar a consulta um pouco mais:
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;

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

Portanto, agora tenho o texto “Nível da coluna” ou “Nível da tabela” sendo retornado, dependendo de qual seja.

Eu também uso o ISNULL() função para transformar qualquer valor NULL em “(n/a)”.

E também adicionei o is_disabled coluna à lista, caso alguma das restrições tenha sido desativada. Você sempre pode dar a esta coluna o mesmo tratamento que o parent_column_id coluna e apresentar “Sim” ou “Não” ou “Ativado” ou “Desativado” ou similar.