【问题标题】:How to pass the value of a postgres array to asyncpg connection.execute as parameter?如何将 postgres 数组的值作为参数传递给 asyncpg connection.execute?
【发布时间】:2021-11-22 07:50:58
【问题描述】:

我正在尝试构建一段代码,它使用asyncpg 将内容添加到我的 postgres 数据库中的表中,定义如下:

CREATE TABLE my_table (
    id              SERIAL NOT NULL UNIQUE,
    nested_field    varchar(100) NOT NULL UNIQUE,
    subfields       varchar(100)[]
);

从我的 POV 来看,困难的部分是将内容保存到 postgres array variable

我构建的代码如下:

try:
    await connection.execute(query, thing_string, subfields_string)
    return None
except (Exception, asyncpg.UniqueViolationError) as integrError:
    # some other action
except (Exception, asyncpg.ConnectionFailureError) as error:
    # some other action
finally:
    # some other action

query 运行的位置定义为:

query = """
    INSERT INTO my_table(thing, subfields) 
    VALUES($1,$2);
    """

还有args*

(here are the docs about args* 函数 connection.execute 的 asyncpg 参数)

将作为 $1 和 $2 放入字符串中

  1. thing_string,定义为thing_string = "something"

  2. subfields_string,通过运行获得

subfields_string = from_list_to_stringified_set(list_of_subfields)

在哪里

list_of_subfields = ["one, two, three"]

函数定义如下:

def from_list_to_stringified_set(list_of_subfields):
    """
    Given a list of subfields
    [ "subfield1", "subfield2", "subfield3" ]
    it returns
    '{ "subfield1", "subfield2", "subfield3" }'
    """
    subfields_string = ""
    for subfield in list_of_subfields:
        subfields_string = subfields_string + '", "' + subfield
    subfields_string = '{' + subfields_string[3:] + '"}'
    return subfields_string

这样subfields_string的值就会产生'{"one, two, three"}'(这个结果是我的代码正确实现的)。

为了正常工作,在数据库上运行的查询应该是:

# desired result
INSERT INTO my_table(title, subfields) 
VALUES('something','{"one", "two", "three"}');

但是,当我尝试运行我得到的脚本时

asyncpg.exceptions.DataError: invalid input for query argument $2: '{"one", "two", "three"}' (a sized iterable container expected (got type 'str'))

所以connection.execute(...) 不接受我的第二个参数subfields_string,其值为'{"one, two, three"}',因为显然它想要一个可迭代对象而不是字符串。

但是为什么呢?

我作为args* 的一部分传递给connection.execute(...) 的其他参数也是字符串,那么为什么第二个参数被拒绝而第一个被接受?

我怎样才能更改我的代码以获得# desired result

【问题讨论】:

    标签: python arrays string postgresql asyncpg


    【解决方案1】:

    使用字符串列表作为参数。

        query = """
            INSERT INTO my_table(nested_field, subfields) 
            VALUES($1,$2);
            """
        thing_string = 'something'
        subfields_string = ["one", "two", "three"]
        await connection.execute(query, thing_string, subfields_string)
    

    subfields 列是一个 varchar 数组。它对应的 Python 类型是一个列表,如 in the documentation

    所述

    【讨论】:

    • 所以我不需要将 asyncpg 输入从 list_of_subfields 转换为 subfields_string,听起来很符合逻辑。我无法想到每个需要通过 asyncpg 填写数组字段的人都必须实现一个字符串化函数......谢谢!
    • 原来 asyncpg 比你想象的更聪明,好消息!
    猜你喜欢
    • 1970-01-01
    • 2019-08-05
    • 2023-03-24
    • 2017-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-06
    • 1970-01-01
    相关资源
    最近更新 更多