[英]What's the best way to create a dev version of a SQL Server database?
我刚刚从其他人那里继承了一个项目,我想知道是否有一种简单的方法来识别数据库中的所有关系依赖项,以便您可以轻松地从生产中删除大量数据以创建开发人员副本,但保留其余帐户的关系完好无损。
This will give you the "template SQL" in the correct order. 这将为您提供正确顺序的“模板SQL”。
But you'll have to fill in some missing where clause stuff (not trivial). 但是,您必须填写一些缺少的where子句(并非无关紧要)。
;
with cteTableHierarchy
as ( /* Select all table without (selfreferencing) FK */
select distinct
1 as LevelID
, OBJECT_SCHEMA_NAME(Parent.object_id) as TableOwner
, Parent.name as TableName
, Parent.object_id as TbObjID
from sys.objects Parent
left join sys.foreign_key_columns RefKey
On RefKey.parent_object_id = Parent.object_id
and RefKey.parent_object_id <> RefKey.referenced_object_id
and RefKey.constraint_column_id = 1
where RefKey.parent_object_id is null
and Parent.type = 'U'
and Parent.name <> 'dtproperties'
UNION ALL
/* add tables that reference the anchor rows */
SELECT H.LevelID + 1
, OBJECT_SCHEMA_NAME(Parent.object_id) as TableOwner
, OBJECT_NAME(Parent.object_id) as TableName
, Parent.object_id as TbObjID
from sys.objects Parent
inner join sys.foreign_key_columns RefKey
On RefKey.parent_object_id = Parent.object_id
and RefKey.parent_object_id <> RefKey.referenced_object_id
and RefKey.constraint_column_id = 1
inner join cteTableHierarchy H
on H.TbObjID = RefKey.referenced_object_id
where Parent.type = 'U'
and Parent.name <> 'dtproperties'
)
select distinct * , TemplateSQL = 'Delete from [' + TableOwner + '].[' + TableName + '] Where .... '
from cteTableHierarchy
order by LevelID desc -- descending order = order of row deletes
, TableOwner
, TableName ;
EDIT ........................ 编辑........................
Comment out the "Select *" and uncomment the "Delete deleteAlias" to actually perform the deletes. 注释掉“选择*”,然后取消注释“删除deleteAlias”以实际执行删除。 The good thing about this little syntax sugar (Select * vs "Delete deleteAlias" is you can quickly see the EXACT data (via the select *) that you are going to actually delete "Delete deleteAlias". 关于这个小的语法糖(选择*与“删除deleteAlias”)的好处是,您可以快速(实际上通过选择*)看到要删除“删除deleteAlias”的精确数据。
The below populates a small @Holder variable table. 下面填充了一个小的@Holder变量表。 Then will reverse walk the 3 tables.......to delete the data. 然后将反向移动3个表.......以删除数据。
Note, the last table (from dbo.[Customers] deleteAlias) has some redundant/unnecessary code, but I'm trying to show the concept over "conciseness". 注意,最后一个表(来自dbo。[Customers] deleteAlias)具有一些冗余/不必要的代码,但是我试图展示“简洁”概念。
Use Northwind
Go
/* Example to Delete all Order-Details, Orders, Customers based on a known list of CustomerID's */
declare @CustomerIDHolder table ( CustomerID char(5) )
INSERT INTO @CustomerIDHolder ( CustomerID )
Select 'ALFKI' union all select '33333'
--Delete deleteAlias
Select *
from dbo.[Order Details] deleteAlias
where exists
( select null from dbo.[Orders] innerOrds join dbo.Customers innerCusts on innerOrds.CustomerID = innerCusts.CustomerID
where
/* exists inner to outer relationshiop */
innerOrds.OrderId = deleteAlias.OrderId
and
/* filter */
exists ( Select null from @CustomerIDHolder innerInnerHolder where innerInnerHolder.CustomerID = innerCusts.CustomerID )
)
--Delete deleteAlias
Select *
from dbo.[Orders] deleteAlias
where exists
( select null from dbo.Customers innerCusts
where
/* exists inner to outer relationshiop */
innerCusts.CustomerID = deleteAlias.CustomerID
and
/* filter */
exists ( Select null from @CustomerIDHolder innerInnerHolder where innerInnerHolder.CustomerID = innerCusts.CustomerID )
)
--Delete deleteAlias
Select *
from dbo.[Customers] deleteAlias
where exists
( select null from dbo.Customers innerCusts
where
/* exists inner to outer relationshiop */
innerCusts.CustomerID = deleteAlias.CustomerID
and
/* filter */
exists ( Select null from @CustomerIDHolder innerInnerHolder where innerInnerHolder.CustomerID = innerCusts.CustomerID )
)
And here is a "Mark things I want to keep, but delete the rest" example........ 这是一个“标记我想保留的东西,但删除其余部分”的示例........
/* Example to Delete all Order-Details, Orders, Customers based on a known list of CustomerID's */
declare @CustomerIDHolder table ( CustomerID char(5) )
INSERT INTO @CustomerIDHolder ( CustomerID )
Select CustomerID from dbo.Customers
/* Keep all the data except for 2 Customers. Aka, The Customers who do NOT exist in the holder table will be deleted.... */
Delete deleteAliasHolder From @CustomerIDHolder deleteAliasHolder where exists ( Select CustID from (Select 'ALFKI' as CustID union all select '33333' as CustID ) as derived1 where derived1.CustID = deleteAliasHolder.CustomerID )
Select CustomerID as DataToKeepCustomerID from @CustomerIDHolder
--Delete deleteAlias
Select *
from dbo.[Order Details] deleteAlias
where exists
( select null from dbo.[Orders] innerOrds join dbo.Customers innerCusts on innerOrds.CustomerID = innerCusts.CustomerID
where
/* exists inner to outer relationshiop */
innerOrds.OrderId = deleteAlias.OrderId
and
/* filter */
not exists ( Select null from @CustomerIDHolder innerInnerHolder where innerInnerHolder.CustomerID = innerCusts.CustomerID )
)
--Delete deleteAlias
Select *
from dbo.[Orders] deleteAlias
where exists
( select null from dbo.Customers innerCusts
where
/* exists inner to outer relationshiop */
innerCusts.CustomerID = deleteAlias.CustomerID
and
/* filter */
not exists ( Select null from @CustomerIDHolder innerInnerHolder where innerInnerHolder.CustomerID = innerCusts.CustomerID )
)
--Delete deleteAlias
Select *
from dbo.[Customers] deleteAlias
where exists
( select null from dbo.Customers innerCusts
where
/* exists inner to outer relationshiop */
innerCusts.CustomerID = deleteAlias.CustomerID
and
/* filter */
not exists ( Select null from @CustomerIDHolder innerInnerHolder where innerInnerHolder.CustomerID = innerCusts.CustomerID )
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.