2013-12-20 3 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, а не просто сказать, что это «довольно просто» и рассказывать, как НЕ делать это? Потому что я когда-то делал что-то вроде ответа Атула Арвинда. – 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)) 

где сопп является подключение к 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

И все остальные ответы без комментариев не кажутся мне разумными. Вместо этого вы могли бы изменить этот пост cw. – alko

+0

Квадратные скобки необходимы, потому что второй аргумент 'execute' - это список (последовательность) параметров. В этом случае первым параметром является другой список. –

9

Обратите внимание, что с psycopg2 вам не нужно делать какие-либо обработки строк для массивов. Это считается плохой практикой, поскольку она подвержена ошибкам и может - в худшем случае - привести к открытию инъекционных атак! Вы всегда должны использовать связанные параметры. В приведенном ниже коде я создам новую таблицу с одним столбцом с типом TEXT[] (как в вашем исходном вопросе). Затем я добавлю новую строку и обновлю все. Таким образом, вы увидите как операции INSERT, так и UPDATE (хотя оба они в значительной степени идентичны).

Существует один Python Гоча, хотя, если вы обновляете только одно значение: cur.execute ожидает оператор SQL в качестве первого аргумента и Iterable, содержащий параметры, которые будут связаны в качестве второго аргумента. Ниже будет не работы:

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, поэтому все значения обновляются. После нескольких исполнений I это дает следующий результат:

>>> 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']") 
Смежные вопросы