Python - 从字典项创建字符串(用于写入 postgresql 数据库)

Python - creating string from dict items (for writing to postgresql db)

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

我有很多不同的数据类型要写入我的 PostGreSQL 数据库中的不同表。我正在尝试编写一个函数,该函数可以根据函数中传递的单个变量写入每个表,并且我想一次写入多于 1 行以优化我的查询。幸运的是 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}]

当rows通过上面这段代码string1变成如下:

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

string1 所示,我只需要删除最外面的括号并将其设为我需要的字符串。到目前为止,我不知道这是如何完成的。所以我的问题是:"How do I format string1 to have my required format?"

稍作修改即可实现。 改变你的鳕鱼片如下

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

当前输出为

元组的元组

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

更改后输出将是

你想要的字符串格式

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

您描述的解决方案不是很好,因为它可能会损害您的数据库——该解决方案不关心转义字符串等。因此 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';'

execute_values 让它更容易。传递字典序列而不是值序列:

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]