Можете да стартирате DBCC CHECKCONSTRAINTS
console команда за връщане на списък с всички нарушения на ограниченията в база данни на SQL Server.
Тази команда проверява целостта на определено ограничение или всички ограничения на определена таблица в текущата база данни. Връща всеки външен ключ и CHECK
нарушения на ограниченията, които установи.
Можете да използвате ALL_CONSTRAINTS
опция за проверка на разрешените и деактивираните ограничения. Ако пропуснете това, тогава се връщат само разрешени ограничения (освен ако не посочите изрично ограничение за проверка, в който случай то ще бъде върнато независимо дали е активирано или деактивирано).
Пример 1 – Нарушени ограничения на CHECK
Изпълних този пример срещу база данни, която съдържа CHECK
нарушения на ограниченията.
USE Test; DBCC CHECKCONSTRAINTS WITH ALL_CONSTRAINTS;
Резултат:
+------------------------+-------------------+---------------------------------------------------------+ | 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' | +------------------------+-------------------+---------------------------------------------------------+
Това показва, че имам три нарушения на ограниченията в моята база данни.
Обяснение на колоните
Трите колони връщат следната информация:
- Таблица
- Име на името на таблицата, което съдържа нарушението на ограничението.
- Ограничение
- Име на ограничението, което е нарушено.
- Къде
- Присвоявания на стойности на колони, които идентифицират реда или редовете, нарушаващи ограничението. Стойността в тази колона може да се използва в
WHERE
клауза наSELECT
заявка на заявка за редове, които нарушават ограничението.
Ето защо, благодарение на третата колона, вече мога да намеря (и актуализирам) всички невалидни данни.
Намерете невалидните данни
Така че, ако погледнем първия ред от моите DBCC CHECKCONSTRAINTS
резултати, виждаме, че можем да намерим неправомерните данни, като използваме [JobTitle] = 'Digital Nomad'
в WHERE
клауза.
Като това:
SELECT * FROM [dbo].[Occupation] WHERE [JobTitle] = 'Digital Nomad';
Резултат:
+----------------+---------------+ | OccupationId | JobTitle | |----------------+---------------| | 7 | Digital Nomad | +----------------+---------------+
Дефиницията на ограничението
Нека да разгледаме действителната дефиниция за chkJobTitle
ограничение:
SELECT Definition FROM sys.check_constraints WHERE name = 'chkJobTitle';
Резултат:
+-------------------------------+ | Definition | |-------------------------------| | ([JobTitle]<>'Digital Nomad') | +-------------------------------+
Това ограничение казва, че стойността на JobTitle колона трябва не бъде Digital Nomad , но дигитален номад все пак успя да влезе в моята база данни!
Актуализирайте данните за нарушение
Можете или да актуализирате нарушителните данни, да ги изтриете или да ги оставите на мира.
В този пример използвам същия WHERE
клауза за актуализиране на стойността:
UPDATE [dbo].[Occupation] SET [JobTitle] = 'Unemployed' WHERE [JobTitle] = 'Digital Nomad';
Сега, ако пусна проверката отново, този запис вече не е проблем и остават само другите два проблема:
DBCC CHECKCONSTRAINTS WITH ALL_CONSTRAINTS;
Резултат:
+------------------------+-------------------+---------------------------------------------------------+ | 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' | +------------------------+-------------------+---------------------------------------------------------+
Пример 2 – Нарушени ограничения на външния ключ
В този пример преминавам към база данни, която съдържа няколко нарушения на ограниченията на външния ключ.
USE Music; DBCC CHECKCONSTRAINTS WITH ALL_CONSTRAINTS;
Резултат:
+----------------+---------------------+--------------------+ | Table | Constraint | Where | |----------------+---------------------+--------------------| | [dbo].[Albums] | [FK_Albums_Artists] | [ArtistId] = '123' | | [dbo].[Albums] | [FK_Albums_Artists] | [ArtistId] = '17' | +----------------+---------------------+--------------------+
В този случай изглежда, че два реда в Албуми таблицата препраща към Идентификатор на изпълнител това не съществува.
Намерете невалидните данни
Отново можем да използваме
Къде
колона, за да изградим нашия WHERE
клауза. Този път ще добавя и двете нарушения към моя WHERE
клауза:
SELECT * FROM [dbo].[Albums] WHERE [ArtistId] = '123' OR [ArtistId] = '17';
Резултат:
+-----------+-------------+---------------+------------+-----------+ | AlbumId | AlbumName | ReleaseDate | ArtistId | GenreId | |-----------+-------------+---------------+------------+-----------| | 21 | Yo Wassup | 2019-03-12 | 17 | 3 | | 22 | Busted | 1901-05-11 | 123 | 3 | +-----------+-------------+---------------+------------+-----------+
Така че вече можем да видим двата реда, които нарушават ограничението (въпреки че това е само ArtistId колона, която нарушава ограничението).
Проверете таблицата с първични ключове
Можем да потвърдим нарушението, като отправим запитване към Изпълнители таблица (т.е. таблицата, която съдържа първичния ключ за този външен ключ).
Така че нека изпълним същата заявка срещу Изпълнители таблица.
SELECT * FROM [dbo].[Artists] WHERE [ArtistId] = '123' OR [ArtistId] = '17';
Резултат:
(0 rows affected)
Както се очаква, нито една от стойностите не е в тази таблица.
Външният ключ трябва да предотврати това да се случи. Или невалидните данни са влезли в базата данни, докато външният ключ е бил деактивиран, или са въведени преди създаването на външния ключ. Така или иначе, когато създавате или разрешавате външен ключ или CHECK
ограничение, трябва да използвате WITH CHECK
за да посочите, че всички съществуващи данни трябва да бъдат проверени, преди да разрешите ограничението.
Пример 3 – Проверете само разрешените ограничения
Ако искате да проверите само ограниченията, които в момента са активирани, премахнете WITH ALL_CONSTRAINTS
:
USE Test; DBCC CHECKCONSTRAINTS;
Резултат:
+--------------------+---------------+------------------------------+ | Table | Constraint | Where | |--------------------+---------------+------------------------------| | [dbo].[Occupation] | [chkJobTitle] | [JobTitle] = 'Digital Nomad' | +--------------------+---------------+------------------------------+
Така че от двете ограничения, които бяха нарушени, изглежда, че chkJobTitle е единствената, която е активирана.
Можем допълнително да проверим това със следната заявка:
SELECT name, is_disabled FROM sys.check_constraints WHERE name = 'chkValidEndDate' OR name = 'chkJobTitle';
Резултат:
+-----------------+---------------+ | name | is_disabled | |-----------------+---------------| | chkJobTitle | 0 | | chkValidEndDate | 1 | +-----------------+---------------+
Пример 4 – Проверете само ограниченията за дадена таблица
Можете да добавите името на таблица в скоби, ако искате да проверите само ограниченията за тази таблица:
USE Test; DBCC CHECKCONSTRAINTS(ConstraintTest) WITH ALL_CONSTRAINTS;
Резултат:
+------------------------+-------------------+---------------------------------------------------------+ | 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' | +------------------------+-------------------+---------------------------------------------------------+
Пример 5 – Проверка на едно ограничение
Можете да проверите едно ограничение, като поставите името му в скоби:
USE Test; DBCC CHECKCONSTRAINTS(chkValidEndDate);
Резултат:
+------------------------+-------------------+---------------------------------------------------------+ | 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' | +------------------------+-------------------+---------------------------------------------------------+
Когато посочите едно ограничение, WITH ALL_CONSTRAINTS
няма ефект:
USE Test; DBCC CHECKCONSTRAINTS(chkValidEndDate) WITH ALL_CONSTRAINTS;
Резултат:
+------------------------+-------------------+---------------------------------------------------------+ | 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' | +------------------------+-------------------+---------------------------------------------------------+