Python 使用psycopg2以列表形式返回PostgreSQL UUID数组
我有一个SQL语句,它包含一个子查询,嵌入在Python 使用psycopg2以列表形式返回PostgreSQL UUID数组,python,postgresql,type-conversion,uuid,psycopg2,Python,Postgresql,Type Conversion,Uuid,Psycopg2,我有一个SQL语句,它包含一个子查询,嵌入在ARRAY()中,如下所示: SELECT foo, ARRAY(SELECT x from y) AS bar ... 查询工作正常,但是在psycopg2结果游标中,数组返回为字符串(如“{1,2,3}”),而不是列表 我的问题是,将这样的字符串转换为python列表的最佳方式是什么?如果每个结果游标数组的格式都是'{x,y,z}',那么您可以这样做来剥离大括号字符串,并通过逗号分隔符将其拆分为一个列表: >>> s = '{1
ARRAY()
中,如下所示:
SELECT foo, ARRAY(SELECT x from y) AS bar ...
查询工作正常,但是在psycopg2结果游标中,数组返回为字符串(如“{1,2,3}”
),而不是列表
我的问题是,将这样的字符串转换为python列表的最佳方式是什么?如果每个结果游标数组的格式都是
'{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']
它适用于我,无需解析:
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')]
另一种处理方法是显式地告诉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'])
row: ([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'A', [u'a0eebc99-9c0b-aef8-bb6d-6bb9bd380a11', u'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a12'])
row: ([u'a0eebc99-9c0b-aef8-bb6d-6bb9bd380a11', u'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a12'],)
诀窍是将
::text
附加到您关心的字段。非常感谢这一点,我又回去玩了一些代码,您是对的,它确实有效,但仅适用于整数和字符串列类型。我在数组中检索的列实际上是UUID类型,它仍然以字符串的形式返回。对不起,当我最初发布时,我过度简化了我的代码,我没有意识到列类型会影响这一点。谢谢,这确实有效。如果我不能找出为什么ARRAY()不适用于UUID字段(见下文),我将采用这种方法。