Python - 从dict项创建字符串(用于写入postgresql db)

时间:2017-05-23 09:56:45

标签: python string postgresql dictionary string-formatting

我正在使用psycopg2编写一些代码来连接到PostGreSQL数据库。

我有很多不同的数据类型要写入PostGreSQL数据库中的不同表。我正在尝试编写一个函数,可以根据函数中传递的单个变量写入每个表,并且我希望一次写入多行以优化我的查询。幸运的是,PostGreSQL允许我这样做:PostGreSQL Insert

INSERT INTO films (code, title, did, date_prod, kind) VALUES
('B6717', 'Tampopo', 110, '1985-02-10', 'Comedy'),
('HG120', 'The Dinner Game', 140, DEFAULT, 'Comedy');

我遇到了一个问题,我希望有人可以帮助我。

我需要创建一个字符串:

string1 = (value11, value21, value31), (value12, value22, value32)

将使用带值的字典创建string1变量。到目前为止,我已经能够创建一个接近我想要的结构的元组。我有一个词典列表。该列表名为rows

string1 = tuple([tuple([value for value in row.values()]) for row in rows])

为了测试它,我创建了以下小rows变量:

rows = [{'id': 1, 'test1': 'something', 'test2': 123},
        {'id': 2, 'test1': 'somethingelse', 'test2': 321}]

当行通过上面的代码时,string1变为如下:

((1, 'something', 123), (2, 'somethingelse', 321))

正如string1所示,我只需要删除最外面的括号,并将其作为一个字符串,以便它可以满足我的需要。到目前为止,我不知道如何做到这一点。所以我的问题是:"如何格式化string1以获得我所需的格式?"

3 个答案:

答案 0 :(得分:2)

只需稍加修改即可实现此目的。 改变你的鳕鱼如下

','.join([tuple([value for value in row.values()]).__repr__() for row in rows])

当前输出

元组的元组

  

(('某事',123,1),(' somethingelse',321,2))

更改输出后

以字符串格式显示

  

"('某事',123,1),(' somethingelse',321,2)"

答案 1 :(得分:2)

execute_values让事情变得更轻松。传递dict序列而不是值序列:

import psycopg2, psycopg2.extras

rows = [
    {'id': 1, 'test1': 'something', 'test2': 123},
    {'id': 2, 'test1': 'somethingelse', 'test2': 321}
]

conn = psycopg2.connect(database='cpn')
cursor = conn.cursor()

insert_query = 'insert into t (id, test1, test2) values %s'
psycopg2.extras.execute_values (
    cursor, insert_query, rows,
    template='(%(id)s, %(test1)s, %(test2)s)',
    page_size=100
)

并插入值:

table t;
 id |     test1     | test2 
----+---------------+-------
  1 | something     |   123
  2 | somethingelse |   321

要使受影响的行数使用CTE:

insert_query = '''
    with i as (
        insert into t (id, test1, test2) values %s
        returning *
    )
    select count(*) from i
'''
psycopg2.extras.execute_values (
    cursor, insert_query, rows,
    template='(%(id)s, %(test1)s, %(test2)s)',
    page_size=100
)
row_count = cursor.fetchone()[0]

答案 2 :(得分:1)

您描述的解决方案不是很好,因为它可能会损害您的数据库 - 该解决方案不关心转义字符串等。因此SQL注入是可能的。 幸运的是,psycopg(和psycopg2)有光标的methods executemogrify,它们将为您正确地完成所有这些工作:

import contextlib

with contextlib.closing(db_connection.cursor()) as cursor:
    values = [cursor.mogrify('(%(id)s, %(test1)s, %(test2)s)', row) for row in rows]
    query = 'INSERT INTO films (id, test1, test2) VALUES {0};'.format(', '.join(values))

对于python 3:

import contextlib

with contextlib.closing(db_connection.cursor()) as cursor:
    values = [cursor.mogrify('(%(id)s, %(test1)s, %(test2)s)', row) for row in rows]
    query_bytes = b'INSERT INTO films (id, test1, test2) VALUES ' + b', '.join(values) + b';'