在double with语句中使用psycopg2执行多个SQL查询



是否可以在使用psycopg2的双with游标打开语句中传递多个查询(首先打开连接,然后打开游标)?

。替换:

import psycopg2
def connector():
return psycopg2.connect(**DB_DICT_PARAMS)
########
sql_update1 = ("UPDATE table SET array = %s::varchar[], "
"array_created = true, timestamp = now() AT TIME ZONE 'UTC' "
"WHERE id = %s")
sql_update2 = ("UPDATE table SET json_field = %s "
"WHERE id = %s")
with connector() as conn:
with conn.cursor() as curs:
curs.execute(sql_update1, [stringArray, ID])
with connector() as conn:
with conn.cursor() as curs:
curs.execute(sql_update2, [jsonString, ID])

由:

#(...)
sql_update1 = ("UPDATE table SET array = %s::varchar[], "
"array_created = true, timestamp = now() AT TIME ZONE 'UTC' "
"WHERE id = %s")
sql_update2 = ("UPDATE table SET json_field = %s "
"WHERE id = %s")
with connector() as conn:
with conn.cursor() as curs:
curs.execute(sql_update1, [stringArray, ID])
curs.execute(sql_update2, [jsonString, ID])

如果第二个查询需要在第一个查询之前完成,如果不需要怎么办?
在此示例中,它们肯定会更新数据库中的相同记录(即行),但不会更新相同字段(即属性或列)。

是否精确授权,因为这两个SQL语句是顺序提交的,即第一个语句先完成。然后,在且仅在第二个执行之后。

或者它实际上是被禁止的,因为它们可以并行执行,每个查询都不知道另一个查询在任何时刻的状态?

数据库中没有花哨的触发器或过程。让我们先简单点。
(请注意,我特意在这里写了两个查询,其中一个查询将完全适合,但情况并非总是如此,因为在将其他一些结果保存到DB中的同一记录之前,一些计算仍然在进行中)。

如果您希望它们同时执行,只需将它们放在用分号分隔的同一字符串中。我有点生疏了,但我认为以下应该可以工作:

sql_updates = ("UPDATE table SET array = %s::varchar[], "
"array_created = true, timestamp = now() AT TIME ZONE 'UTC' "
"WHERE id = %s;"
"UPDATE table SET json_field = %s "
"WHERE id = %s;")
with connector() as conn:
with conn.cursor() as curs:
curs.execute(sql_updates, [stringArray, ID, jsonString, ID])

最好避免这种情况:

with connector() as conn:
with conn.cursor() as curs:
curs.execute(sql_update1, [stringArray, ID])
with connector() as conn:
with conn.cursor() as curs:
curs.execute(sql_update2, [jsonString, ID])

与执行查询相比,打开数据库连接相当慢,因此重用它比为每个查询打开一个新连接要好得多。如果你的程序是一个脚本,通常你只需要在启动时打开连接,在退出时关闭它。

但是,如果您的程序在查询之间花费了很长时间等待,并且将有许多实例正在运行,那么最好关闭连接,以免无所事事地消耗postgres服务器上宝贵的RAM。这在客户端/服务器应用程序中很常见,其中客户端主要等待用户输入。如果有很多客户机,您还可以使用连接池,它提供了两全其美的优点,但代价是增加了一些额外的复杂性。但如果它只是一个脚本,就不需要麻烦了。

with connector() as conn:
with conn.cursor() as curs:
curs.execute(sql_update1, [stringArray, ID])
curs.execute(sql_update2, [jsonString, ID])

这样会更快。您不需要构建新的游标,您可以重用相同的游标。注意,如果在重用游标之前没有获取第一个查询的结果,那么在执行第二个查询之后将无法获取第一个查询的结果,因为游标只存储最后一个查询的结果。因为这些都是更新,所以没有结果,除非您想检查rowcount,看看它是否更新了一行。

如果第二个查询需要在第一个查询之前完成,如果不需要怎么办?

不在乎。Execute()在返回之前处理整个查询,所以当python到达下一个代码位时,查询已经完成。

是否精确授权,因为这两个SQL语句是顺序提交的,即第一个语句先完成。然后,在且仅在第二个执行之后。

是的

或者它实际上是被禁止的,因为它们可以并行执行,每个查询都不知道另一个查询在任何时刻的状态?

如果你想并行执行多个查询,例如,因为一个查询需要一段时间,而你想在执行其他查询的同时执行它,那么你需要几个DB连接,当然每个数据库需要一个python线程,因为execute()会阻塞。它不常用。

最新更新