psycopg2:WHERE =ANY 具有多列

问题描述 投票:0回答:1

PostgreSQL v14 Psycopg2 v2.9.3

我可以直接在 PostgreSQL / pgsql 中执行此操作,但是我似乎无法在 Psycopg2 中实现它。

给出一个示例表:

    CREATE TABLE accounts (
       id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
       account_name TEXT,
       account_number TEXT NOT NULL,
       other_account_info TEXT
    )

    -- Enforces uniqueness for the pair, both non-null
    CREATE UNIQUE INDEX accounts_name_number_unique_idx ON accounts (account_name, account_number);

    -- Enforces uniqueness for the account_number for a non-null account_name
    CREATE UNIQUE INDEX accounts_number_unique_idx ON accounts (account_number) WHERE account_name IS NULL;

我想通过执行以下操作来使用 2 个字段来匹配帐户记录:

SELECT *
FROM accounts
WHERE (account_name, account_number) =ANY(VALUES('name', number'), ('name1', 'number2'))

当我直接在 psql 中运行它时,这当然工作得很好,但是我无法让 psycopg2 正确格式化 SQL。

注意:我不想简单地执行

WHERE account_name = %(account_name)s AND account_number = %(account_number)s
,因为我将有未知数量的 account_name / account_number 对进行查询,并且不想动态生成 SQL。

我尝试过以下方法:

template: str = f"""
SELECT *
FROM accounts
WHERE (account_name, account_number) = ANY(VALUES%(account_list)s)
"""

inserts: dict = {'account_list': ('account_name1', 'account_number1')}
execute(cur=_cursor, sql=template, argslist=inserts)

这有效!但是,一旦我向参数添加第二个 account_name 和 account_number 并将其设为元组的元组,它就会中断:

UndefinedFunction: operator does not exist: text = record

template: str = f"""
SELECT *
FROM accounts
WHERE (account_name, account_number) = ANY(VALUES%(account_list)s)
"""

inserts: dict = { 'account_list': (('account_name1', 'account_number1',),('account_name2', 'account_number2',)) }
execute(cur=_cursor, sql=template, argslist=inserts)

我还尝试将参数设置为列表并从 SQL 模板中删除“VALUES”,但它破坏了,我得到

DatatypeMismatch: cannot compare dissimilar column types text and unknown at record column 1

template: str = f"""
SELECT *
FROM accounts
WHERE (account_name, account_number) = ANY(%(account_list)s)
"""

inserts: dict = { 'account_list': [('account_name1', 'account_number1'),('account_name2', 'account_number2')] }
execute(cur=_cursor, sql=template, argslist=inserts)

我认识到在某些情况下,我需要强制转换各个参数,但我不知道如何在 psycopg2 中执行此操作。

任何帮助将不胜感激!

python postgresql psycopg2
1个回答
0
投票

与使用

any()
相比,使用
unnest()
来创建您感兴趣的 account_name 和 account_number 对的临时表并将其加入到您的帐户表中可能更容易。

sql = "select * from accounts
       join unnest(%(names)s, %(numbers)s) as query(name, number) 
       on query.name = accounts.account_name and 
          query.number = accounts.account_number;"
accounts = (('account_name1', 'account_number1',),
            ('account_name2', 'account_number2',))
names, numbers = = map(list, zip(*accounts))
cur.execute(sql, {"names": names, "number": numbers})
© www.soinside.com 2019 - 2024. All rights reserved.