Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Временно деактивирайте всички ограничения на външния ключ

За да деактивирате ограниченията на външния ключ:

DECLARE @sql NVARCHAR(MAX) = N'';

;WITH x AS 
(
  SELECT DISTINCT obj = 
      QUOTENAME(OBJECT_SCHEMA_NAME(parent_object_id)) + '.' 
    + QUOTENAME(OBJECT_NAME(parent_object_id)) 
  FROM sys.foreign_keys
)
SELECT @sql += N'ALTER TABLE ' + obj + ' NOCHECK CONSTRAINT ALL;
' FROM x;

EXEC sp_executesql @sql;

За да активирате отново:

DECLARE @sql NVARCHAR(MAX) = N'';

;WITH x AS 
(
  SELECT DISTINCT obj = 
      QUOTENAME(OBJECT_SCHEMA_NAME(parent_object_id)) + '.' 
    + QUOTENAME(OBJECT_NAME(parent_object_id)) 
  FROM sys.foreign_keys
)
SELECT @sql += N'ALTER TABLE ' + obj + ' WITH CHECK CHECK CONSTRAINT ALL;
' FROM x;

EXEC sp_executesql @sql;

Въпреки това, няма да можете да отрязвате таблиците, ще трябва да изтриете от тях в правилния ред. Ако трябва да съкратите за тях, трябва да премахнете изцяло ограниченията и да ги създадете отново. Това е лесно да се направи, ако ограниченията на външния ви ключ са прости, ограничени от една колона, но определено по-сложно, ако има множество колони.

Ето нещо, което можете да опитате. За да направите това част от вашия SSIS пакет, ще ви трябва място за съхранение на дефинициите на FK, докато пакетът SSIS работи (няма да можете да правите всичко това в един скрипт). Така че в някаква помощна база данни създайте таблица:

CREATE TABLE dbo.PostCommand(cmd NVARCHAR(MAX));

След това във вашата база данни можете да имате съхранена процедура, която прави това:

DELETE other_database.dbo.PostCommand;

DECLARE @sql NVARCHAR(MAX) = N'';

SELECT @sql += N'ALTER TABLE ' + QUOTENAME(OBJECT_SCHEMA_NAME(fk.parent_object_id))
   + '.' + QUOTENAME(OBJECT_NAME(fk.parent_object_id)) 
   + ' ADD CONSTRAINT ' + fk.name + ' FOREIGN KEY (' 
   + STUFF((SELECT ',' + c.name
    FROM sys.columns AS c 
        INNER JOIN sys.foreign_key_columns AS fkc 
        ON fkc.parent_column_id = c.column_id
        AND fkc.parent_object_id = c.[object_id]
    WHERE fkc.constraint_object_id = fk.[object_id]
    ORDER BY fkc.constraint_column_id 
    FOR XML PATH(''), TYPE).value('.', 'nvarchar(max)'), 1, 1, '')
+ ') REFERENCES ' + 
QUOTENAME(OBJECT_SCHEMA_NAME(fk.referenced_object_id))
+ '.' + QUOTENAME(OBJECT_NAME(fk.referenced_object_id))
+ '(' + 
STUFF((SELECT ',' + c.name
    FROM sys.columns AS c 
        INNER JOIN sys.foreign_key_columns AS fkc 
        ON fkc.referenced_column_id = c.column_id
        AND fkc.referenced_object_id = c.[object_id]
    WHERE fkc.constraint_object_id = fk.[object_id]
    ORDER BY fkc.constraint_column_id 
    FOR XML PATH(''), TYPE).value('.', 'nvarchar(max)'), 1, 1, '') + ');
' FROM sys.foreign_keys AS fk
WHERE OBJECTPROPERTY(parent_object_id, 'IsMsShipped') = 0;

INSERT other_database.dbo.PostCommand(cmd) SELECT @sql;

IF @@ROWCOUNT = 1
BEGIN
  SET @sql = N'';

  SELECT @sql += N'ALTER TABLE ' + QUOTENAME(OBJECT_SCHEMA_NAME(fk.parent_object_id))
    + '.' + QUOTENAME(OBJECT_NAME(fk.parent_object_id)) 
    + ' DROP CONSTRAINT ' + fk.name + ';
  ' FROM sys.foreign_keys AS fk;

  EXEC sp_executesql @sql;
END

Сега, когато вашият SSIS пакет е завършен, той трябва да извика друга съхранена процедура, която прави:

DECLARE @sql NVARCHAR(MAX);

SELECT @sql = cmd FROM other_database.dbo.PostCommand;

EXEC sp_executesql @sql;

Ако правите всичко това само за да можете да съкращавате вместо да изтривате, предлагам просто да вземете удара и да стартирате изтриване. Може да използвате модел за възстановяване с групово регистриран файл, за да сведете до минимум въздействието на регистрационния файл. Като цяло не виждам как това решение ще бъде толкова по-бързо от простото използване на изтриване в правилния ред.

През 2014 г. публикувах по-подробна публикация за това тук:

  • Изхвърлете и създайте отново всички ограничения на външния ключ в SQL Server


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да определим дали числото е с плаваща или цяло число

  2. Намиране на родител от най-високо ниво в SQL

  3. Конкатениране на много редове в един текстов низ с групиране

  4. Как да върнете всички ненадеждни ограничения на външния ключ в SQL Server (пример за T-SQL)

  5. Fix Error Msg 4151 „Типът на първия аргумент за NULLIF не може да бъде константа NULL, защото типът на първия аргумент трябва да бъде известен“ в SQL Server