Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Tymczasowo wyłącz wszystkie ograniczenia klucza obcego

Aby wyłączyć ograniczenia klucza obcego:

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;

Aby ponownie włączyć:

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;

Nie będziesz jednak w stanie skrócić tabele, będziesz musiał usunąć z nich w odpowiedniej kolejności. Jeśli musisz skrócić je, musisz całkowicie usunąć ograniczenia i ponownie je utworzyć. Jest to proste, jeśli wszystkie ograniczenia klucza obcego są proste, jednokolumnowe, ale zdecydowanie bardziej złożone, jeśli zaangażowanych jest wiele kolumn.

Oto coś, czego możesz spróbować. Aby uczynić to częścią pakietu SSIS, potrzebujesz miejsca do przechowywania definicji FK podczas działania pakietu SSIS (nie będziesz w stanie zrobić tego wszystkiego w jednym skrypcie). Więc w jakiejś bazie danych narzędzi utwórz tabelę:

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

Następnie w swojej bazie danych możesz mieć procedurę składowaną, która to robi:

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

Teraz, gdy Twój pakiet SSIS jest gotowy, powinien wywołać inną procedurę składowaną, która:

DECLARE @sql NVARCHAR(MAX);

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

EXEC sp_executesql @sql;

Jeśli robisz to wszystko tylko po to, aby móc obcinać zamiast usuwać, sugeruję po prostu wziąć trafienie i uruchomić usuwanie. Być może użyj modelu odzyskiwania z logowaniem zbiorczym, aby zminimalizować wpływ dziennika. Ogólnie nie widzę, jak to rozwiązanie będzie o wiele szybsze niż samo użycie usuwania we właściwej kolejności.

W 2014 opublikowałem bardziej rozbudowany post na ten temat tutaj:

  • Upuść i ponownie utwórz wszystkie ograniczenia klucza obcego w 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. Najlepsze narzędzie do odzyskiwania SQL na rok 2020 do odzyskiwania kluczowej bazy danych SQL

  2. Czy SQL Server Express LocalDB może być połączony zdalnie?

  3. Jak ustawić sortowanie kolumny w SQL Server (T-SQL)

  4. porównywanie kolumny z listą wartości w t-sql

  5. Jak znaleźć tabele zawierające określoną kolumnę w SQL Server