我有一个非常标准的关系数据情况,其中有一个带有子实体的根实体(和相应的表)。这些孩子有儿童实体等等约6个等级。每个级别都有很多孩子与父母之间的关系。我想编写一个有效复制根实体及其所有子实体的过程(以递归方式复制子项的子项),为每个实体创建新实体,同时将每个实体存储在各自的表中。
我知道这可以用嵌套游标完成,但我不想这样做。我知道有一个更优雅的解决方案,我只需要帮助创建它。我有一种感觉,解决方案在于OUTPUT子句和MERGE语句的组合。
如果可以,请为新手SQL开发人员级别量身定制答案。我将需要一个解释或链接到您使用的任何结构的解释,这些结构超出了基本的SELECT INSERT UPDATE和DELETE。
感谢您的时间。
答案 0 :(得分:0)
您需要使用公用表表达式。检查一下: http://blog.sqlauthority.com/2012/04/24/sql-server-introduction-to-hierarchical-query-using-a-recursive-cte-a-primer/
答案 1 :(得分:0)
我假设您要复制表层次结构中的数据子集。按层次结构,我指的是在明显意义上通过外键相互关联的表。例如,Customers
将是一个根表,Orders
是其子项,OrderDetails
是另一个子项(在第3级)。
首先,我们复制层次结构的根表:
MERGE RootTable as target
USING (
SELECT *
FROM RootTable
WHERE SomeCondition
) AS src
ON 1=2 -- this is so that all rows that do not match will be added
WHEN NOT MATCHED THEN INSERT (AllColumns) VALUES (AllColumns)
OUTPUT src.ID as OldID, INSERTED.ID as NewID INTO #RootTableMapping
现在我们在#RootTableMapping
中对根表的复制源和复制目标ID进行了1比1的映射。此外,还复制了所有根行。
我们现在需要复制所有子表。这是一个声明:
MERGE ChildTable as target
USING (
SELECT *, #RootTableMapping.NewID AS NewParentID
FROM ChildTable
JOIN #RootTableMapping ON ChildTable.RootID = #RootTableMapping.OldID
WHERE SomeCondition
) AS src
WHEN NOT MATCHED THEN INSERT (AllColumns, RootID) VALUES (AllColumns, NewParentID)
这里,我们为每个子行获取克隆的根表行的ID,以便我们可以链接层次结构。为此,我们使用#RootTableMapping
。我们复制所有未修改的列,除了我们用映射中的NewID
替换的父类的ID。
每个子表都需要一个这样的MERGE
语句。通过添加其他连接,该概念还扩展到具有2个以上级别的层次结构。除底层以外的所有级别都必须记录复制源ID到复制目标ID的映射,以允许下面的下一层获取新ID。
如果我没有说清楚一切,请随意提出进一步的问题。我知道这是一个粗略的草图。