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

Cómo encontrar todas las violaciones de restricciones en una base de datos de SQL Server

Puede ejecutar DBCC CHECKCONSTRAINTS comando de consola para devolver una lista de todas las violaciones de restricciones en una base de datos de SQL Server.

Este comando verifica la integridad de una restricción específica o todas las restricciones en una tabla específica en la base de datos actual. Devuelve cualquier clave foránea y CHECK violaciones de restricciones que encuentra.

Puedes usar las ALL_CONSTRAINTS opción para verificar las restricciones habilitadas y deshabilitadas. Si omite esto, solo se devolverán las restricciones habilitadas (a menos que especifique explícitamente una restricción para verificar, en cuyo caso se devolverá independientemente de si está habilitada o deshabilitada).

Ejemplo 1:restricciones CHECK violadas

Ejecuté este ejemplo en una base de datos que contiene algo de CHECK violaciones de restricciones.

USE Test;
DBCC CHECKCONSTRAINTS WITH ALL_CONSTRAINTS;

Resultado:

+------------------------+-------------------+---------------------------------------------------------+
| Table                  | Constraint        | Where                                                   |
|------------------------+-------------------+---------------------------------------------------------|
| [dbo].[Occupation]     | [chkJobTitle]     | [JobTitle] = 'Digital Nomad'                            |
| [dbo].[ConstraintTest] | [chkValidEndDate] | [StartDate] = '2020-01-01' AND [EndDate] = '1999-01-01' |
| [dbo].[ConstraintTest] | [chkValidEndDate] | [StartDate] = '2021-10-25' AND [EndDate] = '2021-10-24' |
+------------------------+-------------------+---------------------------------------------------------+

Esto muestra que tengo tres violaciones de restricciones en mi base de datos.

Explicación de las Columnas

Las tres columnas devuelven la siguiente información:

Mesa
Nombre del nombre de la tabla que contiene la violación de la restricción.
Restricción
Nombre de la restricción que se viola.
Dónde
Asignaciones de valores de columna que identifican la fila o filas que violan la restricción. El valor de esta columna se puede utilizar en un WHERE cláusula de un SELECT declaración que consulta filas que violan la restricción.

Por lo tanto, gracias a la tercera columna, ahora puedo encontrar (y actualizar) todos los datos no válidos.

Encuentra los datos no válidos

Entonces, si miramos la primera fila de mi DBCC CHECKCONSTRAINTS resultados, vemos que podemos encontrar los datos ofensivos usando [JobTitle] = 'Digital Nomad' en un WHERE cláusula.

Así:

SELECT *
FROM [dbo].[Occupation]
WHERE [JobTitle] = 'Digital Nomad';

Resultado:

+----------------+---------------+
| OccupationId   | JobTitle      |
|----------------+---------------|
| 7              | Digital Nomad |
+----------------+---------------+

La definición de restricción

Echemos un vistazo a la definición real de chkJobTitle restricción:

SELECT Definition 
FROM sys.check_constraints
WHERE name = 'chkJobTitle';

Resultado:

+-------------------------------+
| Definition                    |
|-------------------------------|
| ([JobTitle]<>'Digital Nomad') |
+-------------------------------+

Esta restricción dice que el valor de JobTitle la columna debe no nómada digital , ¡sin embargo, un nómada digital logró ingresar a mi base de datos!

Actualizar los datos ofensivos

Puede actualizar los datos ofensivos, eliminarlos o dejarlos solos.

En este ejemplo utilizo el mismo WHERE cláusula para actualizar el valor:

UPDATE [dbo].[Occupation]
SET [JobTitle] = 'Unemployed'
WHERE [JobTitle] = 'Digital Nomad';

Ahora, si vuelvo a ejecutar la verificación, ese registro ya no es un problema y solo quedan los otros dos problemas:

DBCC CHECKCONSTRAINTS WITH ALL_CONSTRAINTS;

Resultado:

+------------------------+-------------------+---------------------------------------------------------+
| Table                  | Constraint        | Where                                                   |
|------------------------+-------------------+---------------------------------------------------------|
| [dbo].[ConstraintTest] | [chkValidEndDate] | [StartDate] = '2020-01-01' AND [EndDate] = '1999-01-01' |
| [dbo].[ConstraintTest] | [chkValidEndDate] | [StartDate] = '2021-10-25' AND [EndDate] = '2021-10-24' |
+------------------------+-------------------+---------------------------------------------------------+

Ejemplo 2:restricciones de clave externa violadas

En este ejemplo, cambio a una base de datos que contiene un par de violaciones de restricciones de clave externa.

USE Music;
DBCC CHECKCONSTRAINTS WITH ALL_CONSTRAINTS;

Resultado:

+----------------+---------------------+--------------------+
| Table          | Constraint          | Where              |
|----------------+---------------------+--------------------|
| [dbo].[Albums] | [FK_Albums_Artists] | [ArtistId] = '123' |
| [dbo].[Albums] | [FK_Albums_Artists] | [ArtistId] = '17'  |
+----------------+---------------------+--------------------+

En este caso, parece que dos filas en Álbumes la tabla hace referencia a un ArtistId eso no existe.

Encuentra los datos no válidos

Nuevamente, podemos usar el Dónde columna para construir nuestro WHERE cláusula. Esta vez agregaré ambas violaciones a mi WHERE cláusula:

SELECT *
FROM [dbo].[Albums]
WHERE [ArtistId] = '123' OR [ArtistId] = '17';

Resultado:

+-----------+-------------+---------------+------------+-----------+
| AlbumId   | AlbumName   | ReleaseDate   | ArtistId   | GenreId   |
|-----------+-------------+---------------+------------+-----------|
| 21        | Yo Wassup   | 2019-03-12    | 17         | 3         |
| 22        | Busted      | 1901-05-11    | 123        | 3         |
+-----------+-------------+---------------+------------+-----------+

Así que ahora podemos ver las dos filas que violan la restricción (aunque es solo el ArtistId columna que viola la restricción).

Consulte la tabla de claves principales

Podemos confirmar la infracción consultando a los Artistas tabla (es decir, la tabla que contiene la clave principal para esta clave externa).

Así que ejecutemos la misma consulta contra los Artistas mesa.

SELECT *
FROM [dbo].[Artists]
WHERE [ArtistId] = '123' OR [ArtistId] = '17';

Resultado:

(0 rows affected)

Como era de esperar, ningún valor está en esa tabla.

Se supone que la clave externa evita que esto suceda. Los datos no válidos ingresaron a la base de datos mientras la clave externa estaba deshabilitada o ingresaron antes de que se creara la clave externa. De cualquier manera, al crear o habilitar una clave externa o CHECK restricción, debe usar WITH CHECK para especificar que todos los datos existentes deben verificarse antes de habilitar la restricción.

Ejemplo 3:marcar solo las restricciones habilitadas

Si solo desea verificar las restricciones que están actualmente habilitadas, elimine WITH ALL_CONSTRAINTS :

USE Test;
DBCC CHECKCONSTRAINTS;

Resultado:

+--------------------+---------------+------------------------------+
| Table              | Constraint    | Where                        |
|--------------------+---------------+------------------------------|
| [dbo].[Occupation] | [chkJobTitle] | [JobTitle] = 'Digital Nomad' |
+--------------------+---------------+------------------------------+

Entonces, de las dos restricciones que se violaron, parece que chkJobTitle es el único que estaba habilitado.

Podemos verificar esto aún más con la siguiente consulta:

SELECT 
  name,
  is_disabled
FROM sys.check_constraints
WHERE name = 'chkValidEndDate' OR name = 'chkJobTitle';

Resultado:

+-----------------+---------------+
| name            | is_disabled   |
|-----------------+---------------|
| chkJobTitle     | 0             |
| chkValidEndDate | 1             |
+-----------------+---------------+

Ejemplo 4:verificar solo las restricciones para una tabla determinada

Puede agregar el nombre de una tabla entre paréntesis si solo desea verificar las restricciones de esa tabla:

USE Test;
DBCC CHECKCONSTRAINTS(ConstraintTest) WITH ALL_CONSTRAINTS;

Resultado:

+------------------------+-------------------+---------------------------------------------------------+
| Table                  | Constraint        | Where                                                   |
|------------------------+-------------------+---------------------------------------------------------|
| [dbo].[ConstraintTest] | [chkValidEndDate] | [StartDate] = '2020-01-01' AND [EndDate] = '1999-01-01' |
| [dbo].[ConstraintTest] | [chkValidEndDate] | [StartDate] = '2021-10-25' AND [EndDate] = '2021-10-24' |
+------------------------+-------------------+---------------------------------------------------------+

Ejemplo 5:Comprobar una sola restricción

Puede comprobar una sola restricción encerrando su nombre entre paréntesis:

USE Test;
DBCC CHECKCONSTRAINTS(chkValidEndDate);

Resultado:

+------------------------+-------------------+---------------------------------------------------------+
| Table                  | Constraint        | Where                                                   |
|------------------------+-------------------+---------------------------------------------------------|
| [dbo].[ConstraintTest] | [chkValidEndDate] | [StartDate] = '2020-01-01' AND [EndDate] = '1999-01-01' |
| [dbo].[ConstraintTest] | [chkValidEndDate] | [StartDate] = '2021-10-25' AND [EndDate] = '2021-10-24' |
+------------------------+-------------------+---------------------------------------------------------+

Cuando especifica una única restricción, el WITH ALL_CONSTRAINTS no tiene efecto:

USE Test;
DBCC CHECKCONSTRAINTS(chkValidEndDate) WITH ALL_CONSTRAINTS;

Resultado:

+------------------------+-------------------+---------------------------------------------------------+
| Table                  | Constraint        | Where                                                   |
|------------------------+-------------------+---------------------------------------------------------|
| [dbo].[ConstraintTest] | [chkValidEndDate] | [StartDate] = '2020-01-01' AND [EndDate] = '1999-01-01' |
| [dbo].[ConstraintTest] | [chkValidEndDate] | [StartDate] = '2021-10-25' AND [EndDate] = '2021-10-24' |
+------------------------+-------------------+---------------------------------------------------------+