5

我有一个 SQL 语句,其中包含一个嵌入的子查询,ARRAY()如下所示:

SELECT foo, ARRAY(SELECT x from y) AS bar ...

查询工作正常,但是在 psycopg2 结果游标中,数组作为字符串(如"{1,2,3}")返回,而不是列表。

我的问题是,将这样的字符串转换为 python 列表的最佳方法是什么?

4

4 回答 4

6

它对我有用,无需解析:

import psycopg2

query = """
    select array(select * from (values (1), (2)) s);
"""

conn = psycopg2.connect('dbname=cpn user=cpn')
cursor = conn.cursor()
cursor.execute(query)
rs = cursor.fetchall()

for l in rs:
    print l[0]

cursor.close()
conn.close()

执行时的结果:

$ python stackoverflow_select_array.py 
[1, 2]

更新

您需要注册 uuid 类型:

import psycopg2, psycopg2.extras

query = """
    select array(
        select *
        from (values
            ('A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11'::uuid),
            ('A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11'::uuid)
        )s
    );
"""

psycopg2.extras.register_uuid()

conn = psycopg2.connect('dbname=cpn user=cpn')
cursor = conn.cursor()
cursor.execute(query)
rs = cursor.fetchall()

for l in rs:
    print l[0]

cursor.close()
conn.close()

结果:

$ python stackoverflow_select_array.py 
[UUID('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'), UUID('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11')]
于 2013-05-28T17:42:14.207 回答
0

如果每个结果游标 ARRAY 的格式为'{x,y,z}',那么您可以这样做以去除大括号的字符串并通过逗号分隔符将其拆分为列表:

>>> s = '{1,2,3}'
>>> s
'{1,2,3}'
>>> l = s.rstrip('}').lstrip('{').split(',')
>>> l
['1', '2', '3']
>>>
>>> s = '{1,2,3,a,b,c}'
>>> s
'{1,2,3,a,b,c}'
>>> l = s.rstrip('}').lstrip('{').split(',')
>>> l
['1', '2', '3', 'a', 'b', 'c']
于 2013-05-28T17:20:45.693 回答
0

另一种处理方法是明确告诉 postgres 你想要文本,然后默认的 psycopg2 字符串解析逻辑将启动,你会得到一个列表:

db = psycopg2.connect('...')
curs = db.cursor()
curs.execute("""
    SELECT s.id, array_agg(s.kind::text)
        FROM (VALUES ('A', 'A0EEBC99-9C0B-AEF8-BB6D-6BB9BD380A11'::uuid),
                     ('A', 'A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A12'::uuid)) AS s (id, kind)
    GROUP BY s.id
""")
for row in curs:
    print "row: {}".format(row)

结果是:

row: (u'A', [u'a0eebc99-9c0b-aef8-bb6d-6bb9bd380a11', u'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a12'])

和查询

curs.execute("""
    SELECT array(
        SELECT s.kind::text
        FROM (VALUES ('A0EEBC99-9C0B-AEF8-BB6D-6BB9BD380A11'::uuid),
                     ('A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A12'::uuid)) AS s (kind))
""")
for row in curs:
    print "row: {}".format(row)

结果是:

row: ([u'a0eebc99-9c0b-aef8-bb6d-6bb9bd380a11', u'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a12'],)

诀窍是专门将 附加::text到您关心的字段。

于 2016-09-21T20:23:32.477 回答
0

解决方案 1

将 UUID 数组转换uuid[]为文本数组text[]

select
    p.name,
    array(
        select _i.item_id
        from items _i
        where _i.owner_id = p.person_id
    )::text[] as item_ids
from persons p;

来自python代码:

import psycopg2.extras
curs = conn.cursor(cursor_factory=extras.DictCursor)  # To get rows in dictionary
curs.execute(my_query)
rows = curs.fetchall()
print(dict(row[0]))

输出:

{
    "name": "Alex",
    "item_ids": [
        "db6c19a2-7627-4dff-a963-b90b6217cb11",
        "db6c19a2-7627-4dff-a963-b90b6217cb11"
    ]
}

解决方案 2

注册 UUID 类型,以便 PostgreSQLuuid可以转换为 python uuid.UUID(参见python UUID 文档)类型。

import psycopg2.extras
psycopg2.extras.register_uuid()

在此之后,您可以使用查询而无需使用::text[].

select
    p.name,
    array(
        select _i.item_id
        from items _i
        where _i.owner_id = p.person_id
    ) as item_ids
from persons p;

DictRow 中的输出将如下所示:

{
    "name": "Alex",
    "item_ids": [
        UUID("db6c19a2-7627-4dff-a963-b90b6217cb11"),
        UUID("db6c19a2-7627-4dff-a963-b90b6217cb11")  # uuid.UUID data type
    ]
}
于 2021-10-30T09:09:56.060 回答