144.复制指定节点及其所有子节点到指定结点的案例

博客介绍了SQL语句复制指定节点及其所有子节点到指定结点的案例,还提及借鉴方式排序法,但未详细展开内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.案例1

CREATE TABLE tb(ID int,PID int,Name nvarchar(10))
INSERT tb SELECT 1,NULL,'山东省'
UNION ALL SELECT 2,1   ,'烟台市'
UNION ALL SELECT 4,2   ,'招远市'
UNION ALL SELECT 3,1   ,'青岛市'
UNION ALL SELECT 5,NULL,'四会市'
UNION ALL SELECT 6,5   ,'清远市'
UNION ALL SELECT 7,6   ,'小分市'
GO

--节点复制处理函数
CREATE FUNCTION f_CopyNode(
@ID     int,      --复制此节点下的所有子节点
@PID   int,       --将@ID下的所有子节点复制到此节点下面
@NewID int=NULL   --新编码的开始值,如果指定为NULL,则为表中的最大编码+1
)RETURNS @t TABLE(OldID int,ID int,PID int)
AS
BEGIN
	IF @NewID IS NULL
		SELECT @NewID=COUNT(*)+1 FROM TB
	DECLARE tb CURSOR LOCAL
	FOR
	SELECT ID FROM tb
	WHERE PID=@ID
	OPEN TB
	FETCH tb INTO @ID
	WHILE @@FETCH_STATUS=0
	BEGIN
		INSERT @t VALUES(@ID,@NewID,@PID)
		SET @NewID=@NewID+1
		IF @@NESTLEVEL<32 --如果递归层数未超过32层(递归最大允许32层)
		BEGIN
			--递归查找当前节点的子节点
			DECLARE @PID1 int
			SET @PID1=@NewID-1
			INSERT @t SELECT * FROM f_CopyNode(@ID,@PID1,@NewID)
			SET @NewID=@NewID+@@ROWCOUNT  --排序号加上子节点个数
		END		
		FETCH tb INTO @ID
	END
	RETURN
END
GO

--调用函数将节点1下面的所有子节点复制到节点5下面
INSERT tb(ID,PID,Name)
SELECT a.ID,a.PID,b.Name
FROM f_CopyNode(1,5,DEFAULT) a,tb b
WHERE a.OldID=b.ID
SELECT * FROM tb
/*--结果
ID          PID         Name       
---------------- ----------------- ---------- 
1           NULL        山东省
2           1           烟台市
4           2           招远市
3           1           青岛市
5           NULL        四会市
6           5           清远市
7           6           小分市
8           5           烟台市
10          5           青岛市
9           8           招远市
--*/

2.借鉴方式排序法

CREATE TABLE tb(ID int,PID int,Name nvarchar(10))
INSERT tb SELECT 1,NULL,'山东省'
UNION ALL SELECT 2,1   ,'烟台市'
UNION ALL SELECT 4,2   ,'招远市'
UNION ALL SELECT 3,1   ,'青岛市'
UNION ALL SELECT 5,NULL,'四会市'
UNION ALL SELECT 6,5   ,'清远市'
UNION ALL SELECT 7,6   ,'小分市'
GO

--节点复制处理函数
CREATE FUNCTION f_CopyNode(
@ID     int,        --复制此节点下的所有子节点
@PID    int,       --将@ID下的所有子节点复制到此节点下面
@NewID  int=NULL --新编码的开始值,如果指定为NULL,则为表中的最大编码+1
)RETURNS @t TABLE(OldID int,ID int,PID int,Level int)
AS
BEGIN
	IF @NewID IS NULL
		SELECT @NewID=COUNT(*) FROM TB
	ELSE
		SET @NewID=@NewID-1
	DECLARE @Level int
	SET @Level=1
	INSERT @t(OldID,PID,Level) SELECT ID,@PID,@Level
	FROM tb
	WHERE PID=@ID
	WHILE @@ROWCOUNT>0
	BEGIN
		UPDATE @t SET @NewID=@NewID+1,ID=@NewID
		WHERE Level=@Level
		SET @Level=@Level+1
		INSERT @t(OldID,PID,Level) SELECT a.ID,b.ID,@Level
		FROM tb a,@t b
		WHERE a.PID=b.OldID
			AND b.Level=@Level-1
	END
	RETURN
END
GO

--调用函数将节点1下面的所有子节点复制到节点5下面
INSERT tb(ID,PID,Name)
SELECT a.ID,a.PID,b.Name
FROM f_CopyNode(1,5,DEFAULT) a,tb b
WHERE a.OldID=b.ID
SELECT * FROM tb
/*--结果
ID          PID         Name       
---------------- ----------------- ---------- 
1           NULL        山东省
2           1           烟台市
4           2           招远市
3           1           青岛市
5           NULL        四会市
6           5           清远市
7           6           小分市
8           5           烟台市
9           5           青岛市
10          8           招远市
--*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值