使用Psycopg2插入Python Dictionary

use*_*608 26 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)')
Run Code Online (Sandbox Code Playgroud)

Clo*_*eto 25

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)))
Run Code Online (Sandbox Code Playgroud)

打印:

insert into song_table (artist,title) values ('artist 1', 'song 1')
Run Code Online (Sandbox Code Playgroud)

Psycopg将a调整tuple为a recordAsIs执行Python的字符串替换所做的操作.

  • 为什么不只使用song.values()作为值呢?:) (2认同)

vik*_*kas 18

您还可以使用a插入多行dictionary.如果您有以下内容:

namedict = ({"first_name":"Joshua", "last_name":"Drake"},
            {"first_name":"Steven", "last_name":"Foo"},
            {"first_name":"David", "last_name":"Bar"})
Run Code Online (Sandbox Code Playgroud)

您可以使用以下方法在字典中插入所有三行:

cur = conn.cursor()
cur.executemany("""INSERT INTO bar(first_name,last_name) VALUES (%(first_name)s, %(last_name)s)""", namedict)
Run Code Online (Sandbox Code Playgroud)

cur.executemany语句将自动遍历字典并为每一行执行INSERT查询.

PS:这个例子来自这里


kha*_*son 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)
Run Code Online (Sandbox Code Playgroud)

关键部分是生成的%s元素字符串,并使用它format,将列表直接传递给execute调用,以便psycopg2可以插入vals列表中的每个项目(从而防止可能的SQL注入).

另一变型中,传递dictexecute,是使用这些线取代vals,vals_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)
Run Code Online (Sandbox Code Playgroud)

  • 我也会将`cols`替换为`[cursor.mogrify(x)for x in cols]`,并将`vals_str`替换为阻止SQL注入. (2认同)
  • 稍微阅读 psycopg2 文档,`mogrify` 可能是不必要的,因为该方法的定义表明 **返回的字符串正是将被发送到运行 execute() 方法或类似方法的数据库的字符串。**,所以我认为在 `execute` 调用期间列和 `%s` 字符串将被 `mogrify`'ed。 (2认同)

Ant*_*aux 7

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))
Run Code Online (Sandbox Code Playgroud)

插入表 ("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))
Run Code Online (Sandbox Code Playgroud)

插入表 ("foo", "bar", "baz") 值 (%(foo)s, %(bar)s, %(baz)s)

根据 psycopg2 文档,尽管字符串连接会产生相同的结果,但不应将其用于此目的:

警告:从不、从不从不使用 Python 字符串连接 ( +) 或字符串参数插值 ( %) 将变量传递给 SQL 查询字符串。甚至不是在枪口下。