我刚刚从其他人那里继承了一个项目,我想知道是否有一种简单的方法可以识别数据库中的所有关系依赖项,以便您可以轻松地从生产中删除大量数据以创建开发人员副本但保留其余帐户的关系完好无损。
问问题
73 次
1 回答
1
这将以正确的顺序为您提供“模板 SQL”。
但是你必须填写一些缺少的 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 ;
编辑 ........................
注释掉“Select *”并取消注释“Delete deleteAlias”以实际执行删除。这个小语法糖(Select * vs “Delete deleteAlias”)的好处是您可以快速查看您将实际删除“Delete deleteAlias”的确切数据(通过 select *)。
下面填充了一个小的@Holder 变量表。然后将反向遍历 3 个表......以删除数据。
请注意,最后一个表(来自 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 )
)
这是一个“标记我想保留的东西,但删除其余的东西”的例子............
/* 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 )
)
于 2013-05-23T17:46:55.110 回答