我有一个 SQL 语句,其中包含一个嵌入的子查询,ARRAY()
如下所示:
SELECT foo, ARRAY(SELECT x from y) AS bar ...
查询工作正常,但是在 psycopg2 结果游标中,数组作为字符串(如"{1,2,3}"
)返回,而不是列表。
我的问题是,将这样的字符串转换为 python 列表的最佳方法是什么?
我有一个 SQL 语句,其中包含一个嵌入的子查询,ARRAY()
如下所示:
SELECT foo, ARRAY(SELECT x from y) AS bar ...
查询工作正常,但是在 psycopg2 结果游标中,数组作为字符串(如"{1,2,3}"
)返回,而不是列表。
我的问题是,将这样的字符串转换为 python 列表的最佳方法是什么?
它对我有用,无需解析:
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')]
如果每个结果游标 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']
另一种处理方法是明确告诉 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
到您关心的字段。
将 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"
]
}
注册 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
]
}