我们很快就会对产品进行一段时间的测试。此产品是带有SQL Server 2008R2后端的Web应用程序。
我们的数据库中有几个模式(Customer,DataEntry和其他一些模式)。
我已经找到了wipe all data in a database的方法,而没有破坏参照完整性或数据结构,这与我们期望的接近。我发现的问题是我们实际上需要一些来自某些表的数据。从本质上讲,我们只想擦除Customers模式。
我们编写了一个脚本,它将为客户加载测试数据,但是有没有办法改变链接文章中的技术以仅定位特定模式?有没有更好的方法来清除模式中的所有数据?
答案 0 :(得分:1)
对我来说也是一个常见的场景。我通常会编写我称之为重置脚本的内容,按照必要的顺序从目标表中删除所有数据以防止引用错误,然后重新设置主键。
DELETE FROM < table 1 >
DELETE FROM < table 2 >
... etc ...
DBCC CHECKIDENT (< table 1 >, RESEED, 0)
DBCC CHECKIDENT (< table 2 >, RESEED, 0)
... etc ...
修改
更全面地回答原始问题。要将数据保留在特定的表中,您需要修改执行删除/截断的代码块,并修改以类似方式重新设置idents的代码。
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 :(得分: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
答案 2 :(得分: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