Sql 如何在同一个表中同时插入具有父行的行(可选)
下表所示为:Sql 如何在同一个表中同时插入具有父行的行(可选),sql,postgresql,postgresql-9.2,Sql,Postgresql,Postgresql 9.2,下表所示为: CREATE TABLE public.parenttest ( id bigserial NOT NULL PRIMARY KEY, mydata varchar(30), parent bigint ) WITH ( OIDS = FALSE ); 我想插入一组行。其中一些行应将之前插入的行的序列生成id作为列父级的值 例如: INSERT INTO parenttest (mydata,parent) VALUES ('rootnod
CREATE TABLE public.parenttest (
id bigserial NOT NULL PRIMARY KEY,
mydata varchar(30),
parent bigint
) WITH (
OIDS = FALSE
);
我想插入一组行。其中一些行应将之前插入的行的序列生成id作为列父级的值
例如:
INSERT INTO parenttest (mydata,parent) VALUES ('rootnode',null);
INSERT INTO parenttest (mydata,parent) VALUES ('child1', /*id of rootnode*/);
INSERT INTO parenttest (mydata,parent) VALUES ('child2', /*id of rootnode*/);
INSERT INTO parenttest (mydata,parent) VALUES ('child2.1', /*id of child 2*/);
INSERT INTO parenttest (mydata.parent) VALUES ('child2.2', /*id of child 2*/);
…应生成以下数据集id、mydata、parent
1,'rootnode',null
2,'child1',1
3,'child2',1
4,'child2.1',3
5,'child2.2',3
在child2.2之前,当我使用
SELECT currval('parenttest_id_seq');
获取家长的身份证,但我会获取child2.2的身份证
对我来说,用尽可能少的客户端请求就可以完成所有必要的工作,这一点很重要——我希望在服务器端生成所有id 如果行的父级为空是可以接受的,我会这样做:
你可以做一些丑陋的事情,比如:
INSERT INTO parenttest (mydata,parent) VALUES ('rootnode',null);
INSERT INTO parenttest (mydata,parent) SELECT 'child1', id FROM parenttest WHERE mydata='rootnode';
INSERT INTO parenttest (mydata,parent) SELECT 'child2', id FROM parenttest WHERE mydata='rootnode';
INSERT INTO parenttest (mydata,parent) SELECT 'child2.1', id FROM parenttest WHERE mydata='child2';
INSERT INTO parenttest (mydata.parent) SELECT 'child2.2', id FROM parenttest WHERE mydata='child2';
我认为正确的做法是使用客户端,在插入“rootnode”后检索其id,然后在INSERT语句中显式发送以下两条id为的语句。经过一些实验,我找到了一个使用匿名PL/PgSQL代码块的解决方案:
DO $$DECLARE
parentid bigint;
BEGIN
INSERT INTO parenttest (mydata) VALUES ('rootnode');
parentid:=currval('parenttest_id_seq');
INSERT INTO parenttest (mydata,parent) VALUES ('child 1',parentid);
INSERT INTO parenttest (mydata,parent) VALUES ('child 2',parentid);
parentid:=currval('parenttest_id_seq');
INSERT INTO parenttest (mydata,parent) VALUES ('child 2.1',parentid),('child 2.2',parentid);
END$$;
可以在来自客户端的单个请求中使用它,并且我不必在客户端生成任何内容,因此这可能是解决我的问题的一个可能的解决方案
编辑:
它可以用如下方式表达:
DO $$DECLARE
parentid bigint;
BEGIN
INSERT INTO parenttest (mydata) VALUES ('Flat') RETURNING id INTO parentid;
INSERT INTO parenttest (mydata, parent) VALUES ('Subflat 1', parentid);
INSERT INTO parenttest (mydata, parent) VALUES ('Subflat 2', parentid)RETURNING id INTO parentid;
INSERT INTO parenttest (mydata, parent) VALUES ('Subflat 2.1', parentid), ('Subflat 2.2', parentid);
END$$;
我不明白你的问题。您可以添加父项并保存其ID,然后插入其他子项/子项。这就是你想要的?我已经在帖子中添加了预期的结果。我希望现在可以理解这一点。既然parent可以为null,那么可以先插入所有行,然后根据mydata值执行检索相应ID的更新吗?也就是说,这些行将短暂地以null parents存在。我个人要么自己管理标识列,要么创建一个临时表,插入数据,然后使用服务器端DO块或函数将其合并到主表中。在大多数情况下,我想这可能是一个可行的解决方案-已经感谢了。不幸的是,不能保证这些值是唯一的。@ THEJED——然后你需要仔细考虑你的数据实际上代表了什么。自动生成的ID都很好,但如果您没有一个自然键来唯一标识行,那么就没有真正的方法来避免出现重复数据。如果必须采用这种方法,我会首先创建一个临时表,其中包含值parent、child、parent、,然后“更新parenttest SET parent=从temp_table中选择id,其中temp_table.parent
DO $$DECLARE
parentid bigint;
BEGIN
INSERT INTO parenttest (mydata) VALUES ('Flat') RETURNING id INTO parentid;
INSERT INTO parenttest (mydata, parent) VALUES ('Subflat 1', parentid);
INSERT INTO parenttest (mydata, parent) VALUES ('Subflat 2', parentid)RETURNING id INTO parentid;
INSERT INTO parenttest (mydata, parent) VALUES ('Subflat 2.1', parentid), ('Subflat 2.2', parentid);
END$$;