2013-04-11 56 views
0

我们即将对产品进行一段时间的测试。该产品是一个带有SQL Server 2008R2后端的Web应用程序。我们的数据库有几个模式(Customer,DataEntry和其他一些模式)。清除方案中的所有数据,保持结构完好

我已经找到了方法wipe all data in a database没有打破参照完整性或数据结构,这接近我们正在寻找的。我发现的问题是我们实际上需要一些表中的一堆数据。实质上,我们只想擦拭Customers模式。

我们已经编写了一个脚本来为客户加载测试数据,但是有没有办法将链接文章中的技术更改为仅针对特定模式?有没有更好的方法来清除模式中的所有数据?

回答

1

对我来说也是一种常见的情况。我通常编写我称之为重置脚本的内容,以防止引用错误所需的顺序从目标表中删除所有数据,然后重新设置主键。

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

编辑

为了更全面地回答原来的问题。要将数据保留在特定的表中,您需要修改执行删除/截断的代码块,并修改以类似方式重新设置这些元素的代码。

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 
1

只需将@schemaID设置为您希望吹掉的模式的名称,剩下的工作就完成了。如果你结束了一个FK依赖循环就会打破,告诉你该怎么办...

Declare @schemaID Nvarchar(256) 
Set  @schemaID = 'Schema' -- Set this to the name of the schema you wish to blow away 

If  Object_ID('tempdb..#tables') Is Not Null Drop Table #tables 
Create Table #tables (tID Int, SchemaName Nvarchar(256), TableName Nvarchar(256)) 

Insert #tables 
Select Row_Number() Over (Order By s.name, so.name), s.name, so.name 
From sysobjects so 
Join sys.schemas s 
     On so.uid = s.schema_id 
Where so.xtype = 'u' 
And  s.name = @schemaID 

Declare @SQL Nvarchar(Max), 
     @schema Nvarchar(256), 
     @table Nvarchar(256), 
     @iter Int = 1, 
     @loopCatch Int = 0 

While Exists (Select 1 
       From #tables) 
Begin 
     Select @schema = SchemaName, 
       @table = TableName 
     From #tables 
     Where tID = @iter 

     If  Exists (Select 1 
         From sysobjects o 
         Join sys.schemas s1 
           On o.uid = s1.schema_id 
         Join sysforeignkeys fk 
           On o.id = fk.rkeyid 
         Join sysobjects o2 
           On fk.fkeyid = o2.id 
         Join sys.schemas s2 
           On o2.uid = s2.schema_id 
         Join #tables t 
           On o2.name = t.TableName Collate Database_Default 
           And s2.name = t.SchemaName Collate Database_Default 
         Where o.name = @table 
         And  s1.name = @schema) 
     Begin 
       Update t 
       Set  tID = (Select Max(tID) From #tables) + 1 
       From #tables t 
       Where tableName = @table 
       And  schemaName = @schema 

       Set  @iter = @iter + 1 
     End 
     Else 
     Begin 
       Set  @Sql = 'Truncate Table [' + @schema + '].[' + @table + ']' 

       Begin Try 
         Exec sp_executeSQL @SQL; 

         Delete t 
         From #tables t 
         Where tableName = @table 
         And  schemaName = @schema 

         Set  @iter = @iter + 1 
       End  Try 
       Begin Catch 
         Print @SQL 

         Update t 
         Set  tID = (Select Max(tID) From #tables) + 1 
         From #tables t 
         Where tableName = @table 
         And  schemaName = @schema 

         Set  @iter = @iter + 1 
         Set  @loopCatch = @loopCatch + 1; 

         If  @loopCatch > 5 
         Begin 
           Select 'WARNING: Endless FK redundancy loop. Drop the constraints and these tables, truncate and reapply constraints manually' 
           Union All 
           Select '[' + SchemaName + '].[' + TableName + ']' 
           From #tables;     

           Break; 
         End      
       End  Catch 
     End 
End 
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