Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Psycopg2插入Python字典_Python_Postgresql_Psycopg2 - Fatal编程技术网

使用Psycopg2插入Python字典

使用Psycopg2插入Python字典,python,postgresql,psycopg2,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)') 应该采取以下措施: song = dict() song['title'] = 'song 1' song['a

将包含多个键的Python字典插入Postgres数据库而不必枚举所有键的最佳方法是什么

我想做一些像

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

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

应该采取以下措施:

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
元素字符串,并以
格式使用该字符串,将列表直接传递给
execute
调用,以便psycopg2可以插入
vals
列表中的每个项(从而防止可能的SQL注入)

另一种变体是将
dict
传递给
execute
,将使用这些行而不是上面的
vals
vals\u str\u list
vals\u 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)
印刷品:

insert into song_table (artist,title) values ('artist 1', 'song 1')

Psycopg将
元组
调整为
记录
,并执行Python的字符串替换所能完成的操作

您还可以使用
字典插入多行。如果您有以下情况:

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:此示例取自

另一种从字典中查询mySQL或pgSQL的方法是使用构造
%(dic_键)s
,它将被字典中的值替换,并由dic_键响应,如
{dic_键:'dic值'}
工作完美,防止注入 已测试: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) #在dict={u'report\u range':None,u'report\u description':None,'user\u id':6,u'rtype':None,u'datapool\u id':1,u'report\u name':u'test suka 1',u'category\u id':3,u'report\u id':None} cursor.execute('插入报表模板(报表id、报表名称、报表描述、报表范围、数据池id、类别id、rtype、用户id)值'\ “(默认,%(报表名称)s、%(报表描述)s、%(报表范围)s、%(数据池id)s、%(类别id)s、%(rtype)s、%(用户id)s)”\ “正在返回”报告id“,(在dict中)
输出:
插入报告模板(报告id、报告名称、报告描述、报告范围、数据池id、类别id、rtype、用户id)值(默认值,E'test suka 1',NULL、NULL、1、3、NULL、6)返回“报告id”;

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

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

文件中给出了两个示例:

在表中插入(“foo”、“bar”、“baz”)值(%s,%s,%s)

在表中插入(“foo”、“bar”、“baz”)值(%(foo)s、%(bar)s、%(baz)s)

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

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


Python具有某些内置功能,例如连接列表,可以使用这些功能生成查询。此外,python字典还提供了键()值(),可分别用于提取列名和列值这是我使用的方法,应该有效。

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)

我还将用
[cursor.mogrify(x)代替
cols
,用
vals\u str
代替
cols
,以阻止SQL注入。我同意这肯定会增加额外的保护。稍微阅读一下psycopg2文档,
mogrify
,可能没有必要,由于该方法的定义表明返回的字符串正是将发送到运行execute()方法或类似方法的数据库的字符串,因此我认为在调用
execute
期间,列和
%s
字符串将被
mogrify
。我认为主要区别在于它是否提前执行了,在调用
execute
之前,或在
execute
过程中。如果以前执行过,它基本上只会在
execute
运行期间返回相同的字符串,因为它已经被mogrified了。如果你想确切地知道发生了什么,比如说,你的日志,提前做可能会有好处。我不知道关于
AsIs
。有趣的是--保存需要处理成倍的
%s
s…我担心这可能会让用户由于转义不充分而容易受到注入攻击,但是-至少使用一个基本示例-单个撇号似乎可以正确转义。我没有时间测试更先进的注入技术,例如(或类似于)下面链接中描述的注入技术,因此与更标准的参数化技术相比,它们可能仍然是一个问题。为什么不直接使用song.values()作为值呢?:)如果我想获取插入行的id,那么该怎么办?获取mogrify需要一个psycopg2.extensions.cursor,但收到了一个'str'for insert_语句,这显然是一个字符串。嗨,vikas,有没有在循环中与cursor.execute()进行性能比较?这是一个非常非常糟糕的主意。引用psycopg文档:“绝不,绝不,绝不,绝不使用Python字符串连接(+)或字符串参数插值(%)将变量传递给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))
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))
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)