是否有可能 运行 两个 sql 在一个循环中背靠背插入?

is is possible to run two sql inserts back to back in a loop?

假设您有一个类似于

的数据循环
for tree in trees:
    tree_type = [t_type]
    tree_owner = [t_owner]

所以循环的一个结果看起来像

magnolia
Bill

您的两个表如下所示,_id 列是自动递增 PK

tree_header

tree_header_id tree_type
25 云杉色

tree_detail

tree_detail_id tree_id tree_owner
2 25 苏珊
3 25 罗杰

是否可以使用循环来 运行 串联两个插入,将每个结果插入到两个表中,有点像

Insert into tree_header(tree_type) values(tree_type)

last_id = last id inserted into header

Insert into tree_detail(tree_id, tree_owner) values(last_id, tree_owner)

这就是答案。这允许您创建一个循环、设置变量并将它们传递给值。因此,如果您有一个从任何地方返回的数据集 - 只需通过它进入一个循环并将您的数据值分配给变量并将它们传递到插入中。这也将值分开,并且可以在任一插入项下插入多行。

import psycopg2

class MyData():
    def __init__(self, host="10.0.80.85", db="hhh", user="postgres", password="5bebfakee11"):
        self.conn = psycopg2.connect(host=host, database=db, user=user, password=password)
        self.cur = self.conn.cursor() 
            
    def close(self):
        self.cur.close()
        self.conn.close()


db = MyData()
insert = "INSERT INTO hhh.header (col1, col2) VALUES (%s, %s) RETURNING header_id;"
db.cur.execute(insert, ('variant1', 'true' ,))

last_header_id = db.cur.fetchone()[0]

insert = "INSERT INTO hhh.detail (header_id) VALUES (%s)"
db.cur.execute(insert, (last_header_id,))

db.conn.commit()
db.close()

你实际上可以做到这一点是一个单一的声明。该技术是创建一个 CTE 来接收参数。在这种情况下,树类型和所有者数组。然后是第二个 CTE,用于插入 tree_header 和 return 生成的 ID。最后,将参数与结果 header 连接起来。参见 Demo

with parms (tree, owners) as
     ( values ('<tree type>', array ['<Owner_Array>']) )
   , make_tree as
     ( insert into tree_header(tree_type)
         select tree from parms
         returning tree_id, tree_type
     )
insert into  tree_detail(owner_name, tree_id)
   select unnest (p.Owner_Array), mt.tree_id
     from parms p 
     join make_tree mt on (mt.tree_type = p.tree);

现在因为我不写你的晦涩语言(Python?)我不知道它是如何翻译的。但我猜是这样的:

import psycopg2

class MyData():
    def __init__(self, host="10.0.80.85", db="hhh", user="postgres", password="5bebfakee11"):
        self.conn = psycopg2.connect(host=host, database=db, user=user, password=password)
        self.cur = self.conn.cursor() 
            
    def close(self):
        self.cur.close()
        self.conn.close()


 db = MyData()
 statement = "with parms (tree, owners) as                   \
                  ( values ('%',  array [%]) )               \
                , make_tree as                               \
                  ( insert into tree_header(tree_type)       \
                      select tree from parms                 \ 
                      returning tree_id, tree_type           \ 
                  )                                          \
             insert into  tree_detail(owner_name, tree_id)   \
                select unnest (p.owners), mt.tree_id         \
                  from parms p                               \ 
                  join make_tree mt on (mt.tree_type = p.tree);"

 db.cur.execute(statement, (last_header_id,list_owner_array))
 
 db.conn.commit()
 db.close()

注意:语句中没有任何内容 return,它可以解决 Postgres 抛出和异常问题。