0

まもなく製品のテスト期間を迎える予定です。この製品は、SQL Server 2008R2 バックエンドを備えた Web アプリケーションです。

私たちのデータベースには、その中にいくつかのスキーマがあります (Customer、DataEntry、およびその他のいくつか)。

参照整合性やデータ構造を壊さずにデータベース内のすべてのデータを消去する方法を見つけました。これは、私たちが目指していることに近いものです。私が見つけた問題は、実際にはいくつかのテーブルから大量のデータが必要だということです。基本的に、Customers スキーマのみを消去します。

顧客用のテスト データをロードするスクリプトを作成しましたが、リンク先の記事の手法を変更して、特定のスキーマのみを対象とする方法はありますか? スキーマ内のすべてのデータを消去するより良い方法はありますか?

4

3 に答える 3

1

これは、データベースとスキーマでパラメーター化されます。スキーマが指定されていない場合、指定されたデータベース内のすべてのデータが消去されます。

制約を無効にすることで、外部キー参照を含むテーブルを適切に処理します。通常は失敗するはずの手順が失敗した場合は、問題の原因を修正した後に正常に実行することを確認してください。これにより、制約チェックが正常に戻ることが保証されます。

スキーマ間に外部キーがある場合、これは外部キー参照を正しく処理しませんが、これを処理するためにかなり簡単に修正できます。

create procedure [removeData] (@database_name sysname, @schema_name sysname = null)
as
    set nocount on

    create table #tables (
        TableName varchar(900) not null primary key,
        HasFKRef bit not null
    );

    declare @sql nvarchar(4000),
            @table_name varchar(900);

    if (db_id(@database_name) is null)
        raiserror ('You must at least specify the database name', 16, 1);

    set @sql = 'select ''['' + TABLE_CATALOG + ''].['' + TABLE_SCHEMA + ''].['' + TABLE_NAME + '']'' as TableName, (case when exists(select * from [' + @database_name + '].INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc inner join [' + @database_name + '].INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc on rc.UNIQUE_CONSTRAINT_CATALOG = tc.CONSTRAINT_CATALOG and rc.UNIQUE_CONSTRAINT_SCHEMA = tc.CONSTRAINT_SCHEMA and rc.UNIQUE_CONSTRAINT_NAME = tc.CONSTRAINT_NAME where tc.TABLE_NAME = t.TABLE_NAME) then 1 else 0 end) as HasFKRef
        from [' + @database_name + '].INFORMATION_SCHEMA.TABLES t
        where TABLE_TYPE = ''BASE TABLE'' and TABLE_SCHEMA = isnull(@schema_name, TABLE_SCHEMA)';

    insert into #tables
        exec sp_executesql @sql, N'@schema_name sysname', @schema_name;

    declare @curse cursor 
    set @curse = cursor fast_forward for
    select sql from (
        select 'alter table ' + TableName + ' nocheck constraint all' as sql, 1 as sort
        from #tables
        union all
        select 'truncate table ' + TableName, 2 as sort
        from #tables
        where HasFKRef = 0
        union all
        select 'delete from ' + TableName, 3 as sort
        from #tables
        where HasFKRef = 1
        union all
        select 'alter table ' + TableName + ' with check check constraint all', 4 as sort
        from #tables
    ) t
    order by sort, sql

    open @curse

    fetch next from @curse into @sql

    while (@@fetch_status = 0)
    begin
        exec (@sql)

        fetch next from @curse into @sql
    end

    close @curse
GO
于 2013-04-11T15:23:48.223 に答える
1

私にとってもよくあるシナリオです。私は通常、リセット スクリプトと呼ぶものを作成し、参照エラーを防ぐために必要な順序でターゲット テーブルからすべてのデータを削除してから、主キーを再シードします。

DELETE FROM < table 1 >
DELETE FROM < table 2 >
... etc ...    
DBCC CHECKIDENT (< table 1 >, RESEED, 0)
DBCC CHECKIDENT (< table 2 >, RESEED, 0)
... etc ...

編集

元の質問により完全に答えるには。特定のテーブルにデータを残すには、削除/切り捨てを行うコード ブロックを変更する必要があり、同様の方法で ID を再シードするコードも変更する必要があります。

EXEC sp_MSForEachTable '
    IF object_id(''?'') != < table name > AND object_id(''?'') != < table name > AND ... etc ...
    BEGIN
        IF OBJECTPROPERTY(object_id(''?''), ''TableHasForeignRef'') = 1
            DELETE FROM ?
        ELSE
            TRUNCATE TABLE ?
    END
'
GO
于 2013-04-11T14:18:22.090 に答える