2013-12-20 59 views
4

我有一个列表:Python列表到PostgreSQL阵列

[u'ABC', u'DEF', u'GHI'] 

我有将其插入到一个PostgreSQL数组: (ALTER TABLE "aTable" ADD COLUMN "Test" text[];

用于添加数据到PostgreSQL的语法是:

update "aTable" SET "Test" = '{"ABC", "DEF", "GHI"}' 

如何将列表转换为正确的格式?

+3

这是一个非常简单的任务,到目前为止您尝试过了什么? – alko

回答

1
list = [u'ABC', u'DEF', u'GHI'] 
list = str(map(str, list)) 

list = list.replace('[', '{').replace(']', '}').replace('\'', '\"') 

query = '''update "aTable" SET "Test" = '%s\'''' %(list) 
print query 

将导致对,

update "aTable" SET "Test" = '{"ABC", "DEF", "GHI"}' 
+8

结束部分在sql最佳实践方面不正确。罕见地建议将值包含在已执行的sql中,而建议使用绑定变量。 – alko

+0

thx ...对我有用 – saromba

+0

@alko你可以发布如何在sql最佳实践中做到这一点,而不仅仅是说它是“非常简单”,并告诉如何不这样做?因为我曾经像Atul Arvind的回答自己做过一次或两次.. – cptPH

1

在SQL处理变量的正确方法是绑定变量的使用。据我所知,这对于MySQL和Oracle DB来说至关重要,我相信PostgreSQL也是如此。

所以更好的代码是沿线

def as_array(l): 
    l2str = ','.join('"{}"'.format(x) for x in l) 
    return '{{{}}}'.format(l2str) 

query = '''update "aTable" SET "Test" = %s''' 
lst = [u'ABC', u'DEF', u'GHI'] 

cur = conn.cursor() 
cur.execute(query, as_array(lst)) 

其中conn是到PostgreSQL数据库的连接。

+1

thx这个答案,我无法测试它的权利现在要么,但我会尽量记住下次我需要这个;-) – cptPH

+0

这是不需要的。绑定值将自动被正确绑定。没有必要调用'as_array'。我会在第二个添加一个例子。 – exhuma

4

您只需将该列表作为参数传递给execute即可。你不需要做任何特别的事情。 Psycopg将Python列表转换为合适的PostgreSQL数组文字。

import psycopg2 as dbapi 

conn = dbapi.connect(dsn='') 
c = conn.cursor() 
x = [u'ABC', u'DEF', u'GHI'] 
c.execute('update "aTable" SET "Test" = %s', [x]) 
+0

是那些在执行中用'[x]'括起来的方括号?并且你有'''括号的数量错误。 – alko

+0

并没有任何评论downvoting所有其他答案似乎并不合理。您可以修改该链接。 – alko

+0

方括号是必需的,因为'execute'的第二个参数是参数列表(序列)。在这种情况下,第一个参数恰好是另一个列表。 –

9

请注意,使用psycopg2您不需要为数组执行任何字符串处理。这被认为是不好的做法,因为它容易出错,并且可能 - 在最坏的情况下 - 导致打开注入攻击!你应该总是使用绑定参数。在下面的代码中,我将创建一个只有一列的新表格,其类型为TEXT[](如您的原始问题)。然后,我将添加一个新行,并更新所有行。所以你会看到一个INSERTUPDATE操作(尽管两者几乎完全相同)。

有一个Python的疑难杂症但如果你只有一个值更新:cur.execute预计包含的参数被绑定为第二个参数的SQL语句作为第一个参数和迭代。下面就工作:

stmt = 'UPDATE foo SET example_value=%s' 
new_values = ['a', 'b', 'c'] 
cur.execute(stmt, (new_values)) 

的原因是(new_values)被蟒蛇视为new_values(括号中在此情况下下降,他们不被视为元组)。这将导致错误提供3个值('a','b''c')作为要绑定的值,但查询中只有一个占位符(%s)。相反,你必须按如下方式指定它(注意在末尾加逗号):

stmt = 'UPDATE foo SET example_value=%s' 
new_values = ['a', 'b', 'c'] 
cur.execute(stmt, (new_values,)) 

这将会使Python看到(new_values,)作为一个元组(这是一个迭代器)一个元素,它匹配查询占位。有关尾部逗号的更详细说明,请参阅the official docs on tuples

或者,你也可以写[new_values]代替(new_values,),但是 - 在我看来 - (new_values,)是清洁元组是不可改变的,而列表是可变的。


这里与我测试表:

CREATE TABLE foo (
    values TEXT[] 
); 

而这里的Python代码都插入和更新值:

from psycopg2 import connect 


conn = connect('dbname=exhuma') 
cur = conn.cursor() 

cur.execute('INSERT INTO foo VALUES (%s)', (['a', 'b'],)) 

print('>>> Before update') 
cur.execute('SELECT * FROM foo') 
for row in cur: 
    print(type(row[0]), repr(row[0])) 

print('>>> After update') 

cur.execute('UPDATE foo SET example_values = %s', 
      (['new', 'updated', 'values'],)) 

cur.execute('SELECT * FROM foo') 
for row in cur: 
    print(type(row[0]), repr(row[0])) 

cur.close() 
conn.commit() 
conn.close() 

在每次执行时,该代码就会插入新行使用相同的数组值,然后执行没有WHERE子句的更新,以便更新所有值。经过几次处决后,我给出了以下输出:

>>> Before update 
(<type 'list'>, "['new', 'updated', 'values']") 
(<type 'list'>, "['new', 'updated', 'values']") 
(<type 'list'>, "['new', 'updated', 'values']") 
(<type 'list'>, "['new', 'updated', 'values']") 
(<type 'list'>, "['new', 'updated', 'values']") 
(<type 'list'>, "['a', 'b']") 
>>> After update 
(<type 'list'>, "['new', 'updated', 'values']") 
(<type 'list'>, "['new', 'updated', 'values']") 
(<type 'list'>, "['new', 'updated', 'values']") 
(<type 'list'>, "['new', 'updated', 'values']") 
(<type 'list'>, "['new', 'updated', 'values']") 
(<type 'list'>, "['new', 'updated', 'values']")