sql >> Database teknologi >  >> RDS >> Sqlserver

Deaktiver midlertidigt alle begrænsninger for fremmednøgle

Sådan deaktiveres begrænsninger for fremmednøgle:

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;

Sådan genaktiveres:

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;

Du vil dog ikke være i stand til at afkorte tabellerne, bliver du nødt til at slette fra dem i den rigtige rækkefølge. Hvis du har brug for at trunkere dem, skal du helt droppe begrænsningerne og genskabe dem. Dette er nemt at gøre, hvis dine fremmednøglebegrænsninger alle er simple, enkeltkolonne begrænsninger, men absolut mere komplekst, hvis der er flere kolonner involveret.

Her er noget du kan prøve. For at gøre dette til en del af din SSIS-pakke skal du have et sted til at gemme FK-definitionerne, mens SSIS-pakken kører (du vil ikke være i stand til at gøre alt dette i ét script). Så i en eller anden hjælpedatabase skal du oprette en tabel:

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

Så i din database kan du have en lagret procedure, der gør dette:

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

Nu når din SSIS-pakke er færdig, skulle den kalde en anden lagret procedure, som gør:

DECLARE @sql NVARCHAR(MAX);

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

EXEC sp_executesql @sql;

Hvis du gør alt dette bare for at kunne afkorte i stedet for at slette, foreslår jeg, at du bare tager hit og kører en sletning. Brug måske bulk-logget gendannelsesmodel for at minimere virkningen af ​​loggen. Generelt kan jeg ikke se, hvordan denne løsning vil være så meget hurtigere end blot at bruge en sletning i den rigtige rækkefølge.

I 2014 publicerede jeg et mere udførligt indlæg om dette her:

  • Slip og genskab alle fremmednøglebegrænsninger i SQL Server


  1. Socketfil /var/pgsql_socket/.s.PGSQL.5432 mangler i Mountain Lion (OS X Server)

  2. Vælg forespørgsel med offset-grænse er for langsom

  3. Skift en eksisterende kolonne til en beregnet kolonne i SQL Server (T-SQL-eksempel)

  4. Tabeller og indekser vs. HDD og SSD