使用Psycopg2插入Python Dictionary

时间:2015-04-05 20:34:31

标签: python postgresql psycopg2

将带有多个密钥的python字典插入Postgres数据库而不必枚举所有密钥的最佳方法是什么?

我想做点像......

song = dict()
song['title'] = 'song 1'
song['artist'] = 'artist 1'
...

cursor.execute('INSERT INTO song_table (song.keys()) VALUES (song)')

6 个答案:

答案 0 :(得分:21)

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调整为recordAsIs执行Python的字符串替换所做的工作。

答案 1 :(得分:16)

您还可以使用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

答案 2 :(得分:11)

这些方面应该做的事情:

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的另一种变体是使用这些行代替上面的valsvals_str_listvals_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)

答案 3 :(得分:4)

为此目的创建了新的sql模块,并添加到psycopg2版本2.7中。根据文件:

  

如果需要动态生成SQL查询(例如动态选择表名),可以使用psycopg2.sql模块提供的工具。

文档中给出了两个示例:http://initd.org/psycopg/docs/sql.html

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字符串连接(+)或字符串参数插值({{1将变量传递给SQL查询字符串。甚至在枪口下也没有。

答案 4 :(得分:1)

查询mySQL或pgSQL从字典的另一种方法是使用构造%(dic_key)s,它将被字典中的值替换为dic_key,如{'dic_key': 'dic value'} 工作完美,并防止sqlInjection 测试:Python 2.7 见下文:

# 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)

<小时/> OUT: 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";

答案 5 :(得分:0)

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)