You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在psycopg2中同时传入可迭代与非可迭代参数执行SQL语句

报错原因

你遇到的报错是因为executemany的入参格式不符合要求:该方法的第二个参数必须是参数序列组成的可迭代对象,每一个子序列对应一次SQL执行的入参。你当前传入的(person_id, role_id_list)会被psycopg2解析为第一次执行的参数是person_id(整数类型),尝试对其索引取参数值就触发了int不支持索引的报错。

解决方案

方案1:正确使用executemany(无需手动写for循环执行SQL)

只需要提前把固定值person_id和每个角色ID拼接成单次执行的参数元组,构造符合要求的参数序列即可:

def delete_person_roles(person_id, role_id_list):
    sql = "DELETE FROM person_roles WHERE person_id = %s AND role_id = %s;"
    conn = None
    try:
        conn = psycopg2.connect(
            host="localhost",
            database="mydatabase",
            user="myuser",
            password="mypassword")
        cur = conn.cursor()
        # 构造executemany需要的参数序列:每个元素对应一次执行的参数元组
        params = [(person_id, role[0]) for role in role_id_list]
        cur.executemany(sql, params)
        conn.commit()
        cur.close()
    except (Exception, psycopg2.DatabaseError) as error:
        print(error)
    finally:
        if conn is not None:
            conn.close()

方案2:单条SQL执行(性能更优,推荐)

不需要用executemany,直接用PostgreSQL的ANY语法适配列表参数,只需要一次数据库请求就能完成所有匹配记录的删除,性能比多次执行更好:

def delete_person_roles(person_id, role_id_list):
    # 用ANY语法匹配列表中的所有role_id
    sql = "DELETE FROM person_roles WHERE person_id = %s AND role_id = ANY(%s);"
    conn = None
    try:
        conn = psycopg2.connect(
            host="localhost",
            database="mydatabase",
            user="myuser",
            password="mypassword")
        cur = conn.cursor()
        # 把元组列表转为整数列表作为入参
        role_ids = [item[0] for item in role_id_list]
        cur.execute(sql, (person_id, role_ids))
        conn.commit()
        cur.close()
    except (Exception, psycopg2.DatabaseError) as error:
        print(error)
    finally:
        if conn is not None:
            conn.close()

内容的提问来源于stack exchange,提问作者jjepsuomi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.08 05:24:03