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パッケージの一部にするには、SSISパッケージの実行中にFK定義を保存する場所が必要です(これをすべて1つのスクリプトで実行することはできません)。したがって、一部のユーティリティデータベースで、テーブルを作成します。

    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年に、これに関するより詳細な投稿をここに公開しました:

    • SQLServerですべての外部キー制約を削除して再作成する


    1. java-Oracleストアドプロシージャで配列を渡す

    2. ビデオ:RACでのOracle12cIDENTITY列のパフォーマンス

    3. Postgresql COPY TO STDIN with CSVは、競合時にどのように更新しますか?

    4. Oracleでコンマ区切りの文字列を分割する方法