我正在使用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
以获得我所需的格式?"
答案 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 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';'