2016-05-09 4 views
0

Я использую SQL Server 2012 Management Studio. Ниже я пишу. Я бы очень признателен за помощь.sql server 2012 - проверить ограничение

ALTER TABLE [tablename] WITH CHECK ADD CONSTRAINT [constraintname] CHECK 
(([column]='A' OR [column]='B' OR [column]='C' OR [column]='D')) 

Но когда мы создаем скрипт через SQL Server 2012 Management Studio, я получаю ниже заявления ..

ALTER TABLE [tablename] WITH NOCHECK ADD CONSTRAINT [constraintname] CHECK 
(([column]='A' OR [column]='B' OR [column]='C' OR [column]='D')) 
GO 
ALTER TABLE [tablename] CHECK CONSTRAINT [constraintname] 

Почему сгенерированный скрипт первый построенный с NOCHECK, а затем применить проверку на столе ? Что произойдет, если я создам ограничение проверки без nocheck?

ответ

2

Сгенерированный скрипт использует NOCHECK, поэтому ограничение всегда будет создано, даже если значения в таблице не соответствуют. Это лучше для автоматически сгенерированного сценария, так как он гарантирует, что схема базы данных будет создана или изменена правильно.

Сначала я подумал, что второй оператор в сгенерированном скрипте должен гарантировать, что оптимизатор запросов рассмотрит ограничение. (См. Ссылку ниже.) Однако при дальнейшем расследовании кажется, что второе утверждение не имеет никакого эффекта - см. Мой второй ответ.

Когда вы делаете это вручную, используя WITH CHECK, вы можете сразу увидеть, что утверждение не выполнено, и предпримите корректирующие действия. Затем запустите инструкцию еще раз.

Если вы используете опцию WITH NOCHECK, вы можете не заметить, что данные недействительны. Лично я всегда использую WITH CHECK, когда ALTER TABLE добавляет ограничения. Также Books Online говорит, что использование WITH NOCHECK не рекомендуется, за исключением редких случаев - см. Ссылки ниже.

Чтобы продемонстрировать разницу, давайте сначала создадим таблицу и введем некоторые значения.

CREATE TABLE dbo.T 
(
    id int NOT NULL IDENTITY(1,1), 
    [column] nchar(1) NOT NULL 
); 

INSERT INTO dbo.T ([column]) 
    VALUES (N'A'), (N'B'), (N'C'), (N'E'); 

Попробуйте изменить таблицу и добавить ограничение, указав WITH CHECK. Это не удается, потому что некоторые данные в таблице не соответствуют ограничению.

ALTER TABLE dbo.T 
    WITH CHECK 
    ADD CONSTRAINT CK_Column CHECK ([column] IN (N'A', N'B', N'C', N'D')); 

enter image description here

Давайте посмотрим, если ограничение было создано, с помощью представления sys.check_constraints системы каталога. Это показывает, что ограничение не создано.

SELECT * 
    FROM sys.check_constraints 
    WHERE [parent_object_id] = OBJECT_ID(N'dbo.T'); 

enter image description here

Попробуйте еще раз, на этот раз указав С NOCHECK. На этот раз он завершается успешно. Однако нет предупреждений о том, что данные в таблице недействительны, что может быть нежелательным.

ALTER TABLE dbo.T 
    WITH NOCHECK 
    ADD CONSTRAINT CK_Column CHECK ([column] IN (N'A', N'B', N'C', N'D')); 

enter image description here

И мы можем проверить, что ограничение проверки было создано.

enter image description here

См Books Online> ALTER TABLE (Transact-SQL): https://msdn.microsoft.com/en-GB/library/ms190273.aspx> WITH CHECK | С NOCHECK

Если вы не хотите проверять новые ограничения CHECK или FOREIGN KEY для существующих данных, используйте WITH NOCHECK. Мы не рекомендуем это делать, за исключением редких случаев. Новое ограничение будет оцениваться во всех последующих обновлениях данных. Любые нарушения ограничений, которые подавляются WITH NOCHECK при добавлении ограничения, могут привести к сбою будущих обновлений, если они обновляют строки данными, которые не соответствуют ограничению.

Причина второго автоматически генерируемый оператор показал здесь:

оптимизатор запросов не учитывает ограничения, которые определяются с NOCHECK. Такие ограничения игнорируются до тех пор, пока они не будут повторно включены, используя таблицу ALTER TABLE WITH CHECK CHECK CONSTRAINT ALL.

1

Рытья немного глубже после моего предыдущего ответа ...

Если мы выполняем следующий оператор после создания СНЕСКА с опцией WITH NOCHECK, мы можем видеть, что ограничение включено (is_disabled = 0), но ему не доверяют.

SELECT name, is_disabled, is_not_trusted 
    FROM sys.check_constraints 
    WHERE [parent_object_id] = OBJECT_ID(N'dbo.T'); 

enter image description here

Запуск второго утверждения, порожденную SSMS, не имеет никакого значения. Ограничение проверки по-прежнему не проверено, и оно уже включено.

ALTER TABLE dbo.T 
    CHECK CONSTRAINT CK_Column; 

Мы должны исправить данные. (Или измените ограничение.)

UPDATE dbo.T 
    SET [column] = N'D' 
    WHERE [column] = N'E'; 

Затем запустите это утверждение. Обратите внимание, что на этот раз мы указываем WITH CHECK, поэтому данные проверяются.

ALTER TABLE dbo.T 
    WITH CHECK 
    CHECK CONSTRAINT CK_Column; 

Тогда, наконец, мы можем видеть, что ограничение становится доверенным (is_not_trusted = 0), что означает, что он может использоваться оптимизатором запросов.

SELECT name, is_disabled, is_not_trusted 
    FROM sys.check_constraints 
    WHERE [parent_object_id] = OBJECT_ID(N'dbo.T'); 

enter image description here

Таким образом, в целом, второе заявление, порожденное SSMS не служит никакой полезной цели, насколько я могу видеть, потому что ограничение уже включено.

Смотреть Книги Online> sys.check_constraints (Transact-SQL): https://msdn.microsoft.com/en-GB/library/ms187388.aspx

Также см Books Online> ALTER TABLE (Transact-SQL): https://msdn.microsoft.com/en-GB/library/ms190273.aspx> {Проверяем | NOCHECK} CONSTRAINT

Указывает, что имя ограничения включено или отключено. Этот параметр можно использовать только с ограничениями FOREIGN KEY и CHECK. Когда указывается NOCHECK, ограничение отключается, а будущие вставки или обновления в столбце не проверяются относительно условий ограничения.DEFAULT, PRIMARY KEY и UNIQUE ограничения не могут быть отключены.

SQLServerCentral.com> A Проверить и ограничение внешнего ключа повышает производительность запросов: http://www.sqlservercentral.com/articles/Performance+Tuning/71264/