sql >> Base de Datos >  >> RDS >> Sqlserver

Averigüe si una restricción CHECK es de nivel de columna o de tabla en SQL Server (ejemplos de T-SQL)

Cuando creas un CHECK restricción en SQL Server, es posible que ni siquiera piense si se trata de una restricción a nivel de tabla o una restricción a nivel de columna.

Un CHECK a nivel de tabla la restricción se aplica a la tabla, mientras que una restricción a nivel de columna se aplica a una columna específica. Con un CHECK a nivel de tabla restricción, es la fila que se verifica cuando verifica los datos. Con un CHECK a nivel de columna restricción, es la columna específica la que está marcada.

Por lo general, sabrá si la restricción que está creando es una restricción de nivel de tabla o de columna por la definición que le dé. Si solo se verifica una columna en la expresión, será una restricción de nivel de columna. De lo contrario, será una restricción a nivel de tabla.

Pero, ¿cómo sabe si sus restricciones existentes son de nivel de columna o de tabla?

Puede ejecutar cualquiera de los ejemplos de código a continuación para determinar si sus restricciones existentes son de nivel de columna o de tabla. Estos recuperan todos los CHECK restricciones para la base de datos actual, pero siempre puede usar un WHERE cláusula para reducirla a una restricción específica.

Ejemplo 1:consulta básica

Aquí hay una consulta simple que devuelve información básica sobre todos los CHECK restricciones en la base de datos actual.

Aquí, consulto el sys.check_constraints vista del sistema (que devuelve una fila para cada objeto que es un CHECK restricción, con sys.objects.type = 'C' ). Solo devuelvo cuatro columnas (pero siéntete libre de devolver tantas columnas como quieras).

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

La forma más rápida de determinar qué restricciones son restricciones de nivel de tabla es buscar el cero ( 0 ) en el parent_column_id columna. Cualquier cosa con un cero es un CHECK de nivel de tabla restricción. Un valor distinto de cero indica que es un CHECK de nivel de columna restricción definida en la columna con el valor de ID especificado.

Entonces, en este ejemplo, hay tres restricciones a nivel de columna y una restricción a nivel de tabla.

Tenga en cuenta que hay dos restricciones con el mismo parent_column_id (3), sin embargo, estas dos restricciones son de diferentes tablas. El 3 hace referencia a la tercera columna de sus respectivas tablas.

Como se mencionó, si solo desea información sobre una restricción específica, use un 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)) |
+----------+----------------+--------------------+---------------+

Ejemplo 2:mejorar la consulta

Podemos mejorar el ejemplo anterior devolviendo el nombre de la columna principal en lugar de solo su ID. Por supuesto, esto devolverá el nombre de la columna solo para las restricciones de nivel de columna. Para restricciones a nivel de tabla, se devolverá 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;

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

Ejemplo 3:mejoras adicionales

Modifiquemos la consulta un poco más:

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

Así que ahora tengo el texto "Nivel de columna" o "Nivel de tabla", dependiendo de cuál sea.

También uso el ISNULL() función para convertir cualquier valor NULL en "(n/a)".

Y también agregué is_disabled columna a la lista, en caso de que alguna de las restricciones haya sido deshabilitada. Siempre puede darle a esta columna el mismo tratamiento que a parent_column_id y presente "Sí" o "No" o "Habilitado" o "Deshabilitado" o similar.