167

Я ищу способ временно отключить все ограничения DB (например, отношения таблицы).Временно отключить ограничения (MS SQL)

Мне нужно скопировать (используя INSERT) таблицы одного БД в другую БД. Я знаю, что могу добиться этого, выполняя команды в правильном порядке (чтобы не нарушать отношения).

Но было бы проще, если бы я временно отключил проверку ограничений и включил его после завершения операции.

Возможно ли это?

+3

Это не полная копия, я просто хочу, чтобы скопировать выбранные таблицы между – Maciej

+13

Уважаемыми людьми из будущего: Вы можете отключить и повторно включить все ограничения в базе данных сразу; см. http://stackoverflow.com/a/161410 – brichins

+1

Не забудьте включить ограничения, когда это будет сделано! –

ответ

184

Вы можете отключить ограничения FK и CHECK только в SQL 2005+ . См ALTER TABLE

ALTER TABLE foo NOCHECK CONSTRAINT ALL 

или

ALTER TABLE foo NOCHECK CONSTRAINT CK_foo_column 

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

+1

Но это не временно. –

+0

@NicolasBarbulesco: это зависит. Да, это значит, что вы можете снова включить их с DROP/CREATE – gbn

+0

Этот ответ - это только первая половина решения. Я искал простой способ временно отключить ограничения, и я пришел к выводу, что его нет в Oracle. –

55

И, если вы хотите, чтобы убедиться, что вы не нарушили ваши отношения и введены сиротам, как только вы повторно вооружившись чеки, т.е.

ALTER TABLE foo CHECK CONSTRAINT ALL 

или

ALTER TABLE foo CHECK CONSTRAINT FK_something 

тогда вам может вернуться назад и выполнить обновление по любым проверенным столбцам:

UPDATE myUpdatedTable SET someCol = someCol, fkCol = fkCol, etc = etc 

И любые ошибки на th в точке будет вызвано несоблюдением ограничений.

+9

Лучший способ: ALTER TABLE FOO WITH CHECK CHECK CONSTRAINT FK_something –

+1

ALTER TABLE foo CHECK CONSTRAINT ALL или ALTER TABLE foo CHECK CONSTRAINT FK_something будет включать ограничения, но без проверки данных, а это означает, что ограничение будет ненадежным (is_no_trusted = 1, is_disabled = 0). –

16

Фактически вы можете отключить все ограничения базы данных в одной команде SQL и снова включить их при вызове другой отдельной команды. См:

Сейчас я работаю с SQL Server 2005, но я почти уверен, что этот подход работал с SQL Server 2000, а

2

Отключение и включение всех внешних ключей

CREATE PROCEDURE pr_Disable_Triggers_v2 
    @disable BIT = 1 
AS 
    DECLARE @sql VARCHAR(500) 
     , @tableName VARCHAR(128) 
     , @tableSchema VARCHAR(128) 

    -- List of all tables 
    DECLARE triggerCursor CURSOR FOR 
     SELECT t.TABLE_NAME AS TableName 
      , t.TABLE_SCHEMA AS TableSchema 
     FROM INFORMATION_SCHEMA.TABLES t 
     ORDER BY t.TABLE_NAME, t.TABLE_SCHEMA 

    OPEN triggerCursor 
    FETCH NEXT FROM triggerCursor INTO @tableName, @tableSchema 
    WHILE (@@FETCH_STATUS = 0) 
    BEGIN 

     SET @sql = 'ALTER TABLE ' + @tableSchema + '.[' + @tableName + '] ' 
     IF @disable = 1 
      SET @sql = @sql + ' DISABLE TRIGGER ALL' 
     ELSE 
      SET @sql = @sql + ' ENABLE TRIGGER ALL' 

     PRINT 'Executing Statement - ' + @sql 
     EXECUTE (@sql) 

     FETCH NEXT FROM triggerCursor INTO @tableName, @tableSchema 

    END 

    CLOSE triggerCursor 
    DEALLOCATE triggerCursor 

Во-первых, курсор foreignKeyCursor объявляется как оператор SELECT , который собирает список внешних ключей и их имена таблиц. Затем открывается курсор и выполняется начальная инструкция FETCH. Этот оператор FETCH будет считывать данные первой строки в локальные переменные @foreignKeyName и @tableName. При циклическом перемещении курсора вы можете проверить @@ FETCH_STATUS на значение 0, которое указывает, что выборка прошла успешно. Это означает, что цикл будет продолжать двигаться вперед, чтобы он мог получить каждый последующий внешний ключ из набора строк. @@ FETCH_STATUS доступен для всех курсоров на подключении .Поэтому, если вы перебираете несколько курсоров, необходимо указать значение @@ FETCH_STATUS в заявлении сразу после инструкции FETCH. @@ FETCH_STATUS отобразит статус самой последней операции FETCH в соединении. Допустимые значения @@ FETCH_STATUS являются:

0 = FETCH был успешным
-1 = FETCH была неудачной
-2 = строка, которая была уши отсутствует

Внутри цикла, код строит Команда ALTER TABLE по-разному в зависимости от того, является ли намерение отключить или активировать ограничение ключа (с использованием ключевого слова CHECK или NOCHECK). Заявление равно , а затем напечатано в виде сообщения, чтобы его можно было наблюдать, а затем выполнялся оператор . Наконец, когда все строки были итерированы , хранимая процедура закрывает и освобождает курсор.

см Disabling Constraints and Triggers from MSDN Magazine

137
-- Disable the constraints on a table called tableName: 
ALTER TABLE tableName NOCHECK CONSTRAINT ALL 

-- Re-enable the constraints on a table called tableName: 
ALTER TABLE tableName WITH CHECK CHECK CONSTRAINT ALL 
--------------------------------------------------------- 

-- Disable constraints for all tables: 
EXEC sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT all' 

-- Re-enable constraints for all tables: 
EXEC sp_msforeachtable 'ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all' 
--------------------------------------------------------- 
+0

Я думаю, что ваши вызовы хранимой процедуры должны иметь одинарные кавычки? – kevinc

+1

@kevinc no. Пока вы согласны, это не имеет значения. –

+2

Используя цитированные идентификаторы, я считаю стандартную настройку ANSI, а это значит, что вы не должны использовать их для строк. Не имеет никакого отношения к тому, чтобы быть последовательным. см. http://stackoverflow.com/questions/1992314/what-is-the-difference-between-single-and-double-quotes-in-sql – kevinc