Временно отключите ограничения (MS SQL)

208

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

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

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

Это возможно?

Маца
источник
3
Это не полная копия. Я просто хочу скопировать выбранные таблицы между
Maciej
Моя забота о том, чтобы это сделать, - это отключает ограничения для всех, а не только для вас. Если вам необходимо это сделать, сначала переведите базу данных в однопользовательский режим. В противном случае вы можете столкнуться с проблемами целостности данных.
HLGEM
13
Уважаемые люди из будущего: вы можете отключить и снова включить все ограничения в базе данных одновременно; см. stackoverflow.com/a/161410
brichins
1
Не забудьте включить ограничения, когда закончите!
Майк Кристиан
1
@NicolasBarbulesco достаточно справедливо; Я собирался sql-serverи sql-server-2005теги. Ссылка, которую я дал, предназначена для SQL Server, но вы можете сделать то же самое в Oracle - смотрите здесь и здесь . Вы также можете сделать это в PostgreSQL .
Brichins

Ответы:

214

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

ALTER TABLE foo NOCHECK CONSTRAINT ALL

или

ALTER TABLE foo NOCHECK CONSTRAINT CK_foo_column

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

ГБН
источник
10
Но это не временно.
Николас Барбулеско
@NicolasBarbulesco: это зависит. Да, это так, потому что вы можете повторно включить их с помощью DROP / CREATE
gbn
Этот ответ - только первая половина решения. Я искал простой способ временно отключить ограничения, и я пришел к выводу, что он не существует в Oracle.
Николас Барбулеско
Это неправда, что PK и уникальные ограничения не могут быть отключены. По крайней мере, в более поздней версии SQL Server это работает. Например, см: techonthenet.com/sql_server/primary_keys.php
Dejan
1
@NicolasBarbulesco в Oracle? ALTER TABLE some_table DISABLE CONSTRAINT some_table_fk1; // делаем что-то, что нарушает ограничения ALTER TABLE some_table ENABLE CONSTRAINT some_table_fk1;
Стив Суинсбург
237
-- 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'
---------------------------------------------------------
Донал
источник
1
@kevinc нет. Пока вы согласны, это не имеет значения.
Po-Ta-Toe
2
Использование заключенных в кавычки идентификаторов - это, я полагаю, стандартная настройка ANSI, что означает, что вы не должны использовать их для строк. Не имеет ничего общего с тем, чтобы быть последовательным. см stackoverflow.com/questions/1992314/...
kevinc
1
Спасибо за процедуру! И кстати, это правильный корпус "sp_MSforeachtable" (MS прописные буквы). Спасибо!
Сиелу
3
Это должно быть помечено как правильный ответ, так как он полностью отвечает на вопрос. Не только это, но @Donal включал в себя подстановочную версию, которая была очень полезна для меня.
Мэтт Джексон
2
Спасибо за бит включения. Особенно двойной, check checkкоторый многие забывают!
Алекс
57

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

ALTER TABLE foo CHECK CONSTRAINT ALL

или

ALTER TABLE foo CHECK CONSTRAINT FK_something

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

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

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

Майкл К. Кэмпбелл
источник
11
Лучшим способом является ALTER TABLE FOO с ограничением CHECK CHECK FK_something
Cody Konior
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 2000

Кристофа
источник
0

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

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). Затем оператор печатается как сообщение, чтобы можно было наблюдать за его ходом, а затем оператор выполняется. Наконец, когда все строки были повторены, хранимая процедура закрывает и освобождает курсор.

см. Отключение ограничений и триггеров из журнала MSDN

0x49D1
источник