Psycopg2 在 postgres 数据库中插入 python 字典
Psycopg2 insert python dictionary in postgres database
在 python 3+ 中,我想将字典(或 pandas 数据框)中的值插入到数据库中。我选择了带有 postgres 数据库的 psycopg2。
问题是我想不出正确的方法来做到这一点。我可以很容易地连接一个 SQL 字符串来执行,但是 psycopg2 文档明确警告不要这样做。理想情况下,我想做这样的事情:
cur.execute("INSERT INTO table VALUES (%s);", dict_data)
并希望执行能够找出字典的键与 table 中的列相匹配。这没有用。从 psycopg2 文档的示例中我得到了这种方法
cur.execute("INSERT INTO table (" + ", ".join(dict_data.keys()) + ") VALUES (" + ", ".join(["%s" for pair in dict_data]) + ");", dict_data)
我从中得到一个
TypeError: 'dict' object does not support indexing
将字典插入具有匹配列名的 table 的最简单方法是什么?
[建议 answer/workaround - 更好的答案表示赞赏!]
经过一些 trial/error 我得到以下工作:
sql = "INSERT INTO table (" + ", ".join(dict_data.keys()) + ") VALUES (" + ", ".join(["%("+k+")s" for k in dict_data]) + ");"
这给出了 sql 字符串
"INSERT INTO table (k1, k2, ... , kn) VALUES (%(k1)s, %(k2)s, ... , %(kn)s);"
可能由
执行
with psycopg2.connect(database='deepenergy') as con:
with con.cursor() as cur:
cur.execute(sql, dict_data)
Post/cons?
两种解决方案:
d = {'k1': 'v1', 'k2': 'v2'}
insert = 'insert into table (%s) values %s'
l = [(c, v) for c, v in d.items()]
columns = ','.join([t[0] for t in l])
values = tuple([t[1] for t in l])
cursor = conn.cursor()
print cursor.mogrify(insert, ([AsIs(columns)] + [values]))
keys = d.keys()
columns = ','.join(keys)
values = ','.join(['%({})s'.format(k) for k in keys])
insert = 'insert into table ({0}) values ({1})'.format(columns, values)
print cursor.mogrify(insert, d)
输出:
insert into table (k2,k1) values ('v2', 'v1')
insert into table (k2,k1) values ('v2','v1')
我有时 运行 进入这个问题,特别是关于 JSON 数据,我自然希望将其作为字典处理。非常相似。 . .但也许更具可读性?
def do_insert(rec: dict):
cols = rec.keys()
cols_str = ','.join(cols)
vals = [ rec[k] for k in cols ]
vals_str = ','.join( ['%s' for i in range(len(vals))] )
sql_str = """INSERT INTO some_table ({}) VALUES ({})""".format(cols_str, vals_str)
cur.execute(sql_str, vals)
我通常从迭代器内部调用这种类型的东西,并且通常包装在 try/except 中。游标 (cur) 已经在外部作用域中定义,或者可以修改函数签名并传入游标实例。我很少只插入一行。 . .和其他解决方案一样,这允许缺少 cols/values,前提是底层模式也允许它。只要键视图下的字典在插入时没有被修改,就不需要按名称指定键,因为值将按照它们在键视图中的顺序排序。
使用 %(name)s 占位符可能会解决问题:
dict_data = {'key1':val1, 'key2':val2}
cur.execute("""INSERT INTO table (field1, field2)
VALUES (%(key1)s, %(key2)s);""",
dict_data)
你可以在 psycopg2 文档中找到用法 Passing parameters to SQL queries
这是直接插入字典的另一种解决方案
产品型号(有以下数据库列)
name
description
price
image
digital - (defaults to False)
quantity
created_at - (defaults to current date)
解决方法:
data = {
"name": "product_name",
"description": "product_description",
"price": 1,
"image": "https",
"quantity": 2,
}
cur = conn.cursor()
cur.execute(
"INSERT INTO products (name,description,price,image,quantity) "
"VALUES(%(name)s, %(description)s, %(price)s, %(image)s, %(quantity)s)", data
)
conn.commit()
conn.close()
注意:要插入的列在execute语句中指定.. INTO products (column names to be filled) VALUES ..., data <- the dictionary (should be the same **ORDER** of keys)
在 python 3+ 中,我想将字典(或 pandas 数据框)中的值插入到数据库中。我选择了带有 postgres 数据库的 psycopg2。
问题是我想不出正确的方法来做到这一点。我可以很容易地连接一个 SQL 字符串来执行,但是 psycopg2 文档明确警告不要这样做。理想情况下,我想做这样的事情:
cur.execute("INSERT INTO table VALUES (%s);", dict_data)
并希望执行能够找出字典的键与 table 中的列相匹配。这没有用。从 psycopg2 文档的示例中我得到了这种方法
cur.execute("INSERT INTO table (" + ", ".join(dict_data.keys()) + ") VALUES (" + ", ".join(["%s" for pair in dict_data]) + ");", dict_data)
我从中得到一个
TypeError: 'dict' object does not support indexing
将字典插入具有匹配列名的 table 的最简单方法是什么?
[建议 answer/workaround - 更好的答案表示赞赏!]
经过一些 trial/error 我得到以下工作:
sql = "INSERT INTO table (" + ", ".join(dict_data.keys()) + ") VALUES (" + ", ".join(["%("+k+")s" for k in dict_data]) + ");"
这给出了 sql 字符串
"INSERT INTO table (k1, k2, ... , kn) VALUES (%(k1)s, %(k2)s, ... , %(kn)s);"
可能由
执行with psycopg2.connect(database='deepenergy') as con:
with con.cursor() as cur:
cur.execute(sql, dict_data)
Post/cons?
两种解决方案:
d = {'k1': 'v1', 'k2': 'v2'}
insert = 'insert into table (%s) values %s'
l = [(c, v) for c, v in d.items()]
columns = ','.join([t[0] for t in l])
values = tuple([t[1] for t in l])
cursor = conn.cursor()
print cursor.mogrify(insert, ([AsIs(columns)] + [values]))
keys = d.keys()
columns = ','.join(keys)
values = ','.join(['%({})s'.format(k) for k in keys])
insert = 'insert into table ({0}) values ({1})'.format(columns, values)
print cursor.mogrify(insert, d)
输出:
insert into table (k2,k1) values ('v2', 'v1')
insert into table (k2,k1) values ('v2','v1')
我有时 运行 进入这个问题,特别是关于 JSON 数据,我自然希望将其作为字典处理。非常相似。 . .但也许更具可读性?
def do_insert(rec: dict):
cols = rec.keys()
cols_str = ','.join(cols)
vals = [ rec[k] for k in cols ]
vals_str = ','.join( ['%s' for i in range(len(vals))] )
sql_str = """INSERT INTO some_table ({}) VALUES ({})""".format(cols_str, vals_str)
cur.execute(sql_str, vals)
我通常从迭代器内部调用这种类型的东西,并且通常包装在 try/except 中。游标 (cur) 已经在外部作用域中定义,或者可以修改函数签名并传入游标实例。我很少只插入一行。 . .和其他解决方案一样,这允许缺少 cols/values,前提是底层模式也允许它。只要键视图下的字典在插入时没有被修改,就不需要按名称指定键,因为值将按照它们在键视图中的顺序排序。
使用 %(name)s 占位符可能会解决问题:
dict_data = {'key1':val1, 'key2':val2}
cur.execute("""INSERT INTO table (field1, field2)
VALUES (%(key1)s, %(key2)s);""",
dict_data)
你可以在 psycopg2 文档中找到用法 Passing parameters to SQL queries
这是直接插入字典的另一种解决方案
产品型号(有以下数据库列)
name
description
price
image
digital - (defaults to False)
quantity
created_at - (defaults to current date)
解决方法:
data = {
"name": "product_name",
"description": "product_description",
"price": 1,
"image": "https",
"quantity": 2,
}
cur = conn.cursor()
cur.execute(
"INSERT INTO products (name,description,price,image,quantity) "
"VALUES(%(name)s, %(description)s, %(price)s, %(image)s, %(quantity)s)", data
)
conn.commit()
conn.close()
注意:要插入的列在execute语句中指定.. INTO products (column names to be filled) VALUES ..., data <- the dictionary (should be the same **ORDER** of keys)