PGSQL CTE 递归 INSERT RETURNING 自动增量
Posted
技术标签:
【中文标题】PGSQL CTE 递归 INSERT RETURNING 自动增量【英文标题】:PGSQL CTE recursive INSERT RETURNING autoincrement 【发布时间】:2021-11-13 07:25:42 【问题描述】:我有什么:
CREATE TABLE public.treeview_menu_node (
id int8 NOT NULL GENERATED BY DEFAULT AS IDENTITY,
parent_id int8 NULL,
data jsonb NULL,
name varchar NULL,
caption varchar NULL,
CONSTRAINT treeview_menu_node_pk PRIMARY KEY (id)
);
INSERT INTO public.treeview_menu_node
(parent_id, "name")
VALUES(NULL, 'node 1');
INSERT INTO public.treeview_menu_node
(parent_id, "name")
VALUES(1, 'node 1.1');
INSERT INTO public.treeview_menu_node
(parent_id, "name")
VALUES(1, 'node 1.2');
INSERT INTO public.treeview_menu_node
(parent_id, "name")
VALUES(NULL, 'node 2');
INSERT INTO public.treeview_menu_node
(parent_id, "name")
VALUES(4, 'node 2.1');
INSERT INTO public.treeview_menu_node
(parent_id, "name")
VALUES(4, 'node 2.2');
结构:
节点 1 子节点1.1 子节点1.2 节点 2 子节点2.1 子节点2.2我需要什么:
递归复制节点1到节点2
节点 1 子节点1.1 子节点1.2 节点 2 子节点2.1 子节点2.2 节点 1 子节点 1.1 子节点 1.2我的尝试:
WITH RECURSIVE r AS (
INSERT INTO public.treeview_menu_node (parent_id, name, caption, data)
SELECT new_parent_id, name, caption, data
FROM (
SELECT tmn.id, tmn.parent_id, :parent_id::BIGINT new_parent_id, tmn.name, tmn.caption, tmn.data
FROM public.treeview_menu_node tmn
WHERE id IN (:ids)
) t
RETURNING id, parent_id, name, caption, data
UNION ALL
INSERT INTO public.treeview_menu_node (parent_id, name, caption, data)
SELECT new_parent_id, name, caption, data
FROM (
SELECT tmn.id, tmn.parent_id, r.id new_parent_id, tmn.name, tmn.caption, tmn.data
FROM public.treeview_menu_node tmn
JOIN r r ON r.id = tmn.parent_id
) t
RETURNING id, parent_id, name, caption, data
)
SELECT id, parent_id, name, caption, data
FROM r;
地点:
:parent_id 是目的节点id :ids 是要复制的列表或一个节点我得到了什么:
SQL 错误 [42601]:语法错误(近:“UNION”)位置:357
http://sqlfiddle.com/#!17/1e6fa/3
【问题讨论】:
我不太明白你想要什么,但复制数据通常是个坏主意。 您好@LaurenzAlbe,感谢您的帮助。我确定我需要复制什么。最接近的类比:在 Windows 资源管理器中复制文件。 请描述你想要完成的什么,而不仅仅是你如何尝试的sql。这些插入的目标是什么。 【参考方案1】:我找到了解决办法。
不允许在递归 CTE 中进行多次插入。而不是这个,使用函数:
NEXTVAL('table_sequensor_of_autoincrement')
函数返回一个新的 id,就像一个INSERT
命令。因此,您可以使用单个 INSERT
命令准备整个数组以进行插入。
WITH RECURSIVE r AS (
SELECT tmn.id, NEXTVAL('treeview_menu_id_seq') new_id, tmn.parent_id, :parent_id::BIGINT new_parent_id, tmn.name, tmn.caption, tmn.data
FROM public.treeview_menu_node tmn
WHERE id IN (:ids)
UNION ALL
SELECT tmn.id, NEXTVAL('treeview_menu_id_seq') new_id, tmn.parent_id, r.new_id new_parent_id, tmn.name, tmn.caption, tmn.data
FROM public.treeview_menu_node tmn
JOIN r r ON r.id = tmn.parent_id
)
INSERT INTO public.treeview_menu_node (id, parent_id, name, caption, data)
SELECT new_id, new_parent_id, name, caption, data
FROM r;
http://sqlfiddle.com/#!17/1e6fa/10
【讨论】:
以上是关于PGSQL CTE 递归 INSERT RETURNING 自动增量的主要内容,如果未能解决你的问题,请参考以下文章