如何使用可迭代和不可迭代参数在 psycopg2 中执行 SQL 查询

How to execute SQL query in psycopg2 with iterable and non-iterable parameters

我正在尝试使用带有两个参数的 psycopg2 在 PostgreSQL 数据库中执行删除查询:

person_id = 1

role_id_list = [(1,), (2,), (3,)]

因此在数据库中,具有特定 id 的人可以具有特定的“角色”,这些角色由整数元组列表指定。 role_id_list 是元组列表而不是整数列表的原因是因为这是我的另一个 SQL 查询的 return 格式。

无论如何,我想从我的 person_roles table 中删除所有匹配项,其中 perdon_id = 1role_id 在列表 role_id_list[=25= 中]

因为我有一个可迭代对象作为参数,所以我检查了我是否应该使用 psycopg2 中的 executemany-函数:

https://www.psycopg.org/docs/cursor.html#cursor.executemany

所以该函数采用可迭代作为参数,但是如果我像我在示例中那样具有不可迭代和可迭代参数怎么办?

我用以下函数试试运气:

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:
            # read database configuration
            # connect to the PostgreSQL database
            conn = psycopg2.connect(
                host="localhost",
                database="mydatabase",
                user="myuser",
                password="mypassword")
            # create a new cursor
            cur = conn.cursor()
            # execute the DELETE statement
            cur.executemany(sql, (person_id, role_id_list))
            # commit the changes to the database
            conn.commit()
            # close communication with the database
            cur.close()
        except (Exception, psycopg2.DatabaseError) as error:
            print(error)
        finally:
            if conn is not None:
                conn.close()

如果我现在打电话:

delete_person_roles(person_id, role_id_list)

我收到消息:

'int' object does not support indexing

所以我的问题是: 是否可以在不使用 for 循环的情况下在 psycopg2 中同时传递可迭代和不可迭代参数?或者我应该简单地使用 for 循环并逐一删除?

我已经找到了解决方法。通过按以下方式编辑函数中的 SQL-查询:

sql = "DELETE FROM person_roles WHERE person_id = %s AND role_id = ANY(%s);"

然后简单地使用 execute 而不是 executemany 让一切正常。

所以这个函数有效:

def delete_person_roles(person_id, role_id_list):

    sql = "DELETE FROM person_roles WHERE person_id = %s AND role_id = ANY(%s);"
    conn = None
    try:
        # read database configuration
        # connect to the PostgreSQL database
        conn = psycopg2.connect(
            host="localhost",
            database="mydatabase",
            user="myuser",
            password="mypassword")
        # create a new cursor
        cur = conn.cursor()
        # execute the DELETE statement
        cur.execute(sql, (person_id, role_id_list))
        # commit the changes to the database
        conn.commit()
        # close communication with the database
        cur.close()
    except (Exception, psycopg2.DatabaseError) as error:
        print(error)
    finally:
        if conn is not None:
            conn.close()