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 execute
和 mogrify
可以正确地为您完成所有这些工作:
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]
我正在使用 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 execute
和 mogrify
可以正确地为您完成所有这些工作:
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]