什么是最好的方法来插入一个Python字典与许多键到Postgres数据库,而不必枚举所有键?我想做一些...
song = dict() song['title'] = 'song 1' song['artist'] = 'artist 1' ... cursor.execute('INSERT INTO song_table (song.keys()) VALUES (song)')
ruarlubt1#
from psycopg2.extensions import AsIs song = { 'title': 'song 1', 'artist': 'artist 1' } columns = song.keys() values = [song[column] for column in columns] insert_statement = 'insert into song_table (%s) values %s' # cursor.execute(insert_statement, (AsIs(','.join(columns)), tuple(values))) print cursor.mogrify(insert_statement, (AsIs(','.join(columns)), tuple(values)))
图纸:
insert into song_table (artist,title) values ('artist 1', 'song 1')
Psycopg将tuple适配为record,而AsIs则执行Python的字符串替换操作。
tuple
record
AsIs
tzxcd3kk2#
您也可以使用dictionary插入多行。如果您有以下内容:
dictionary
namedict = ({"first_name":"Joshua", "last_name":"Drake"}, {"first_name":"Steven", "last_name":"Foo"}, {"first_name":"David", "last_name":"Bar"})
您可以使用以下命令在字典中插入所有三行:
cur = conn.cursor() cur.executemany("""INSERT INTO bar(first_name,last_name) VALUES (%(first_name)s, %(last_name)s)""", namedict)
cur.executemany语句将自动遍历字典并对每一行执行INSERT查询。PS:这个例子取自here
cur.executemany
nszi6y053#
沿着以下思路应该可以做到这一点:
song = dict() song['title'] = 'song 1' song['artist'] = 'artist 1' cols=song.keys(); vals = [song[x] for x in cols] vals_str_list = ["%s"] * len(vals) vals_str = ", ".join(vals_str_list) cursor.execute("INSERT INTO song_table ({cols}) VALUES ({vals_str})".format( cols = cols, vals_str = vals_str), vals)
关键部分是生成的%s元素字符串,并在format中使用该字符串,将列表直接传递给execute调用,以便 psycopg2 可以插入vals列表中的每个项目(从而防止可能的 *SQL注入 *)。另一个变体,将dict传递到execute,将使用这些行而不是上面的vals,vals_str_list和vals_str:
%s
format
execute
vals
dict
vals_str_list
vals_str
vals_str2 = ", ".join(["%({0})s".format(x) for x in cols]) cursor.execute("INSERT INTO song_table ({cols}) VALUES ({vals_str})".format( cols = cols, vals_str = vals_str2), song)
xu3bshqb4#
新的sql模块是为此目的创建的,并添加到psycopg2版本2.7中。根据文档:如果需要动态生成SQL查询(例如,动态选择表名),可以使用psycopg2.sql模块提供的工具。文档中给出了两个示例:http://initd.org/psycopg/docs/sql.html
sql
names = ['foo', 'bar', 'baz'] q1 = sql.SQL("insert into table ({}) values ({})").format( sql.SQL(', ').join(map(sql.Identifier, names)), sql.SQL(', ').join(sql.Placeholder() * len(names))) print(q1.as_string(conn))
插入到表(“foo”,“bar”,“baz”)值(%s,%s,%s)
q2 = sql.SQL("insert into table ({}) values ({})").format( sql.SQL(', ').join(map(sql.Identifier, names)), sql.SQL(', ').join(map(sql.Placeholder, names))) print(q2.as_string(conn))
插入表(“foo”,“bar”,“baz”)值(%(foo)s,%(bar)s,%(baz)s)虽然字符串连接会产生相同的结果,但根据psycopg2文档,它不应用于此目的:
警告:永远不要,永远不要,永远不要使用Python字符串连接(+)或字符串参数插值(%)将变量传递给SQL查询字符串。即使在枪口下也不行。
+
%
kqqjbcuj5#
另一种从字典**查询mySQL或pgSQL的方法是使用构造%(dic_key)s,它将被字典中与dic_key对应的值替换,如{'dic_key': 'dic value'}工作完美,并防止sqlInjection测试:Python 2.7如下:
%(dic_key)s
{'dic_key': 'dic value'}
# in_dict = {u'report_range': None, u'report_description': None, 'user_id': 6, u'rtype': None, u'datapool_id': 1, u'report_name': u'test suka 1', u'category_id': 3, u'report_id': None} cursor.execute('INSERT INTO report_template (report_id, report_name, report_description, report_range, datapool_id, category_id, rtype, user_id) VALUES ' \ '(DEFAULT, %(report_name)s, %(report_description)s, %(report_range)s, %(datapool_id)s, %(category_id)s, %(rtype)s, %(user_id)s) ' \ 'RETURNING "report_id";', in_dict)
输出:INSERT INTO report_template (report_id, report_name, report_description, report_range, datapool_id, category_id, rtype, user_id) VALUES (DEFAULT, E'test suka 1', NULL, NULL, 1, 3, NULL, 6) RETURNING "report_id";
INSERT INTO report_template (report_id, report_name, report_description, report_range, datapool_id, category_id, rtype, user_id) VALUES (DEFAULT, E'test suka 1', NULL, NULL, 1, 3, NULL, 6) RETURNING "report_id";
p8ekf7hl6#
使用execute_valueshttps://www.psycopg.org/docs/extras.html更快,并且有一个fetch参数来返回一些东西。接下来有一些代码可能会有所帮助。columns是一个字符串,如col_name1, col_name2模板是允许匹配的字符串,如%(col_name1)s, %(col_name2)
execute_values
fetch
col_name1, col_name2
%(col_name1)s, %(col_name2)
def insert(cur: RealDictCursor, table_name: str, values: list[dict], returning: str = '' ): if not values: return [] query = f"""SELECT column_name AS c FROM information_schema.columns WHERE table_name = '{table_name}' AND column_default IS NULL;""" cur.execute(query) columns_names = cur.fetchall() fetch = False if returning: returning = f'RETURNING {returning}' fetch = True columns = '' template = '' for col in columns_names: col_name = col['c'] for val in values: if col_name in val: continue val[col_name] = None columns += f'{col_name}, ' template += f'%({col_name})s, ' else: columns = columns[:-2] template = template[:-2] query = f"""INSERT INTO {table_name} ({columns}) VALUES %s {returning}""" return execute_values(cur, query, values, template=f'({template})', fetch=fetch)
ippsafx77#
Clodaldos的答案在python3的“ordered dict”promise中变得更简单:
from psycopg2.extensions import AsIs song = dict(title='song 1', artist='artist 1') insert_statement = 'insert into song_table (%s) values %s' cursor.execute(insert_statement, (AsIs(','.join(song.keys())), tuple(song.values())))
nvbavucw8#
Python有一些内置的特性,比如join和list,可以用来生成查询。另外,Python字典提供了keys()和values(),可以分别用来提取列名和列值。我就是用这个方法,应该可以用。
song = dict() song['title'] = 'song 1' song['artist'] = 'artist 1' query = '''insert into song_table (''' +','.join(list(song.keys()))+''') values '''+ str(tuple(song.values())) cursor.execute(query)
8条答案
按热度按时间ruarlubt1#
图纸:
Psycopg将
tuple
适配为record
,而AsIs
则执行Python的字符串替换操作。tzxcd3kk2#
您也可以使用
dictionary
插入多行。如果您有以下内容:您可以使用以下命令在字典中插入所有三行:
cur.executemany
语句将自动遍历字典并对每一行执行INSERT查询。PS:这个例子取自here
nszi6y053#
沿着以下思路应该可以做到这一点:
关键部分是生成的
%s
元素字符串,并在format
中使用该字符串,将列表直接传递给execute
调用,以便 psycopg2 可以插入vals
列表中的每个项目(从而防止可能的 *SQL注入 *)。另一个变体,将
dict
传递到execute
,将使用这些行而不是上面的vals
,vals_str_list
和vals_str
:xu3bshqb4#
新的
sql
模块是为此目的创建的,并添加到psycopg2版本2.7中。根据文档:如果需要动态生成SQL查询(例如,动态选择表名),可以使用psycopg2.sql模块提供的工具。
文档中给出了两个示例:http://initd.org/psycopg/docs/sql.html
插入到表(“foo”,“bar”,“baz”)值(%s,%s,%s)
插入表(“foo”,“bar”,“baz”)值(%(foo)s,%(bar)s,%(baz)s)
虽然字符串连接会产生相同的结果,但根据psycopg2文档,它不应用于此目的:
警告:永远不要,永远不要,永远不要使用Python字符串连接(
+
)或字符串参数插值(%
)将变量传递给SQL查询字符串。即使在枪口下也不行。kqqjbcuj5#
另一种从字典**查询mySQL或pgSQL的方法是使用构造
%(dic_key)s
,它将被字典中与dic_key对应的值替换,如{'dic_key': 'dic value'}
工作完美,并防止sqlInjection测试:Python 2.7如下:输出:
INSERT INTO report_template (report_id, report_name, report_description, report_range, datapool_id, category_id, rtype, user_id) VALUES (DEFAULT, E'test suka 1', NULL, NULL, 1, 3, NULL, 6) RETURNING "report_id";
p8ekf7hl6#
使用
execute_values
https://www.psycopg.org/docs/extras.html更快,并且有一个fetch
参数来返回一些东西。接下来有一些代码可能会有所帮助。columns是一个字符串,如col_name1, col_name2
模板是允许匹配的字符串,如%(col_name1)s, %(col_name2)
ippsafx77#
Clodaldos的答案在python3的“ordered dict”promise中变得更简单:
nvbavucw8#
Python有一些内置的特性,比如join和list,可以用来生成查询。另外,Python字典提供了keys()和values(),可以分别用来提取列名和列值。我就是用这个方法,应该可以用。