Тимчасове вимкнення обмежень (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 foo NOCHECK CONSTRAINT ALL

або

ALTER TABLE foo NOCHECK CONSTRAINT CK_foo_column

Первинні ключі та унікальні обмеження неможливо відключити, але це повинно бути нормально, якщо я вас правильно зрозумів.


10
Але це не тимчасово.
Ніколя Барбулеско

@NicolasBarbulesco: це залежить. Так, це означає, що ви можете повторно включити їх за допомогою DROP / CREATE
gbn

Ця відповідь - лише перша половина рішення. Я шукав простий спосіб тимчасового вимкнення обмежень, і я дійшов висновку, що його немає в Oracle.
Ніколя Барбулеско

Це неправда, що ПК та унікальне обмеження неможливо відключити. Принаймні, в більш новій версії SQL Server він працює. Наприклад, дивіться: techonthenet.com/sql_server/primary_keys.php
Деян

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 ні. Поки ти незгодний, це не має значення.
По-та-нозі

2
Використовуючи цитовані ідентифікатори, я вважаю, що стандарт стандарт ANSI, який означає, що ви не повинні використовувати їх для рядків. Не має нічого спільного з послідовністю. см stackoverflow.com/questions/1992314 / ...
kevinc

1
Дякуємо за процедуру! І BTW правильний корпус "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
Кращий спосіб - ВІДПРАВЛЕННЯ ТАБЛИЧНОГО ФОТО З ОБЕРЕЖЕННЯМ ЗАБЕЗПЕЧЕННЯ FK_something
Коді

1
ALTER TABLE foo CHECK CONSTRAINT ALL або ALTER TABLE foo CHECK CONSTRAINT FK_щось дозволить обмеження, але без перевірки даних, а це означає, що обмеження буде недовіреним (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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.