Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何在同一个表中同时插入具有父行的行(可选)_Sql_Postgresql_Postgresql 9.2 - Fatal编程技术网

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$$;