2009-09-23 210 views
30

使psycopg2将参数化查询传递给PostgreSQL的最佳方式是什么?我不想编写自己的escpaing机制或适配器,并且psycopg2源代码和示例很难在Web浏览器中阅读。使用psycopg2/Python DB-API和PostgreSQL的参数化查询

如果我需要切换到像PyGreSQL或另一个python pg适配器,这对我来说没问题。我只是想简单的参数化。

+0

什么样的你想要参数化吗?伪代码样本将很有用。 – whatnick 2009-09-23 15:53:58

+0

Sidenote,你可能想看看SQLAlchemy,在某些方面入门的成本可能会稍微高一些,但它确实是一个非常好的ORM。 – 2009-11-09 18:55:38

+0

为了将来的参考,答案在文档的第一页:http://initd.org/psycopg/docs/usage.html – piro 2011-05-16 16:07:16

回答

60

psycopg2遵循DB-API 2.0的规则(设置在PEP-249中)。这意味着你可以从你的cursor对象中调用execute方法,并使用pyformat绑定样式,它会为你逃脱。例如,下面的应该是安全的(工作):

cursor.execute("SELECT * FROM student WHERE last_name = %(lname)s", 
       {"lname": "Robert'); DROP TABLE students;--"}) 
+42

哈哈,我刚刚得到了......小鲍比桌子! http://xkcd.com/327/ – adam 2010-07-13 14:25:08

+1

所以上面的代码。丢下桌子还是不? – mascot6699 2016-03-26 19:40:07

+1

@ mascot6699它没有,因为查询是参数化的。 – 2017-06-02 18:58:05

13

这里有几个例子,你可能会发现有用

cursor.execute('SELECT * from table where id = %(some_id)d', {'some_id': 1234}) 

或者,你可以动态地构建基于字段名,值的字典查询:

fields = ', '.join(my_dict.keys()) 
values = ', '.join(['%%(%s)s' % x for x in my_dict]) 
query = 'INSERT INTO some_table (%s) VALUES (%s)' % (fields, values) 
cursor.execute(query, my_dict) 

注:该字段必须是在您的代码中定义,不是用户输入,否则您将容易受到SQL注入的影响。

+5

那么除非你知道你在做什么,你应该只是concat输入到SQL查询中,因为它是一个SQL注入。 – 2013-01-25 18:45:40

+3

downvoted由于建议,让你打开SQL注入 – 2014-12-23 05:04:57

+2

@RandySyring这只对SQL注入开放,如果密钥没有很好定义和正确的标识符。值仍然正确参数化。 – cpburnz 2015-04-07 14:17:33

10

从psycopg文档

http://initd.org/psycopg/docs/usage.html

警告决不,决不,决不使用Python字符串串联(+)或字符串参数插值(%)将变量传递给SQL查询字符串。甚至没有枪支。

传递变量在SQL命令的正确的方法是使用execute()方法的第二个参数:

SQL = "INSERT INTO authors (name) VALUES (%s);" # Note: no quotes

data = ("O'Reilly",)

cur.execute(SQL, data) # Note: no % operator