我曾经在 psycopg2 中使用
execute_values
但它在 psycopg3 中消失了。我尝试遵循this答案或这个github帖子中的建议,但它似乎不适用于我的用例。我正在尝试插入多个值,我的 SQL 如下所示:
sql = INSERT INTO activities (type_, key_, a, b, c, d, e)
VALUES %s
ON CONFLICT (key_) DO UPDATE
SET
a = EXCLUDED.a,
b = EXCLUDED.b,
c = EXCLUDED.c,
d = EXCLUDED.d,
e = EXCLUDED.e
values = [['type', 'key', None, None, None, None, None]]
但是做
cursor.executemany(sql, values)
会导致{ProgrammingError}the query has 1 placeholder but 7 parameters were passed
。我尝试了许多带有额外括号等的变体,但总是会导致一些错误。例如,执行 self.cursor.executemany(sql, [values])
会产生 syntax error near or at "$1": Line 3: VALUES $1
。
值子句应由一个
%s
占位符组成,用于插入的每一列,用逗号分隔,并全部放在括号内,如下所示:
INSERT INTO t (a, b, c) VALUES (%s, %s, %s)
我们可以通过字符串操作生成所需的字符串:
# Create one placeholder per column inserted.
placeholders = ', '.join(['%s'] * len(values[0]))
# Wrap in parentheses.
values_clause = f"""({placeholders})"""
# Inject into the query string.
isql = isql % values_clause
with psycopg.connect(dbname='test') as conn, conn.cursor() as cur:
cur.executemany(isql, values)
conn.commit()
但是 psycopg 提供了 tools 来编写 SQL 语句,如果您的查询构建非常动态,那么使用这些工具可能比依赖字符串操作更安全。使用这些工具,您将得到这个(这次我将括号添加到主查询字符串中,因为不这样做没有任何好处):
placeholders = sql.SQL(', ').join(sql.Placeholder() * len(values[0]))
isql = sql.SQL("""INSERT INTO t77716028 (type_, key_, a, b, c, d, e)
VALUES ({placeholders})
ON CONFLICT (key_) DO UPDATE
SET
a = EXCLUDED.a,
b = EXCLUDED.b,
c = EXCLUDED.c,
d = EXCLUDED.d,
e = EXCLUDED.e""")
isql = isql.format(placeholders=placeholders)
with psycopg.connect(dbname='test') as conn, conn.cursor() as cur:
print(f'{isql.as_string(conn)=}')
cur.executemany(isql, values)
conn.commit()