使用我在网络上找到的示例,我创建了一个使用GetReparentedValue重新学习孩子的函数。
但是,当我运行代码时,我收到以下错误:无法在对象中插入重复键。
我理解为什么(因为我试图重新定义孩子,新父母已经有了孩子,所以我需要知道新父结构中孩子的MAX路径(hierarchyid),但我不明白我是怎么做的实际上我会这样做。
路径0x58
oldPath 0x
新路径0x68
SqlCommand command = new SqlCommand("UPDATE Structure SET " +
"Path = " + path + ".GetReparentedValue" +
"(" +
oldPath + ", " + newPath +
")" +
"ParentID = @id " +
"WHERE Path = " + path, _connection);
添加孩子时我必须这样做,所以我认为需要在上面的查询中添加这个,但我不知道path + ".GetDescendant(" + lastChildPath + ", NULL)
数据库表
StructureID int Unchecked
Path hierarchyid Unchecked
PathLevel ([Path].[GetLevel]()) Checked
Description nvarchar(50) Checked
ParentID int Checked
ParentPath ([Path].[GetAncestor]((1))) Checked
有人有任何建议吗?
提前感谢您的帮助: - )
克莱尔
答案 0 :(得分:3)
您可以通过几项更改来实现此功能。首先,您不需要代表要移动的节点的父级的oldPath
。在.GetReparentedValue
函数中,放置正在移动的节点的hierarchyid,即path
中的值。
第二个更改是添加另一个SELECT语句以应用GetDescendant
函数。下面是一个示例脚本,您可以在SQL Server Management Studio(SSMS)中尝试,或者更改以合并到SQLCommand调用中。前几行(变量声明是赋值)仅用于在SSMS中运行。您可以将最后的SELECT
和UPDATE
语句转移到调用代码。
DECLARE @Path hierarchyid
DECLARE @oldPath hierarchyid
DECLARE @newPath hierarchyid
SELECT @Path=0x58, @oldPath=0x, @newPath=0x68
SELECT @newPath = @newPath.GetDescendant(MAX(Path), NULL)
FROM Structure
WHERE path.GetAncestor(1)=@newPath;
UPDATE Structure
SET Path = Path.GetReparentedValue(@Path, @newPath)
WHERE Path = @Path;
您的UPDATE
语句和此修订版仅重新父级单个节点。它不会自动移动移动节点的子节点。移动节点的孩子将成为孤儿。
如果需要移动所选节点和节点的所有后代,可以使用以前语句的以下变体。
DECLARE @Path hierarchyid
DECLARE @oldPath hierarchyid
DECLARE @newPath hierarchyid
SELECT @Path=0x58, @oldPath=0x, @newPath=0x68
SELECT @newPath = @newPath.GetDescendant(MAX(Path), NULL)
FROM Structure
WHERE Path.GetAncestor(1) = @newPath ;
UPDATE Structure
SET Path = Path.GetReparentedValue(@Path, @newPath)
WHERE Path.IsDescendantOf(@Path) = 1;
实际上,从第一个脚本到此脚本的唯一更改是在最后一行。对于Path.IsDescendantOf(@Path) = 1
的所有后代,@Path
测试均属实,包括@Path
。更新后将保持层次关系。
答案 1 :(得分:0)
这是另一个移动子树及其所有子代的示例。它基本上与接受的答案相同。摘自Docs:
CREATE PROCEDURE MoveOrg(@oldMgr nvarchar(256), @newMgr nvarchar(256) )
AS
BEGIN
DECLARE @nold hierarchyid, @nnew hierarchyid
SELECT @nold = OrgNode FROM HumanResources.EmployeeDemo WHERE LoginID = @oldMgr ;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION
SELECT @nnew = OrgNode FROM HumanResources.EmployeeDemo WHERE LoginID = @newMgr ;
SELECT @nnew = @nnew.GetDescendant(max(OrgNode), NULL)
FROM HumanResources.EmployeeDemo WHERE OrgNode.GetAncestor(1)=@nnew ;
UPDATE HumanResources.EmployeeDemo
SET OrgNode = OrgNode.GetReparentedValue(@nold, @nnew)
WHERE OrgNode.IsDescendantOf(@nold) = 1 ;
COMMIT TRANSACTION
END ;
GO