Python支持MySQL预处理语句吗?

rub*_*eet 47 python mysql prepared-statement

我之前参与过一个PHP项目,其中准备好的语句使SELECT查询的速度提高了20%.

我想知道它是否适用于Python?我似乎无法找到任何明确表示它做或不做的事情.

jos*_*rry 58

大多数语言提供了一种做泛型参数化语句的方法,Python也不例外.使用参数化查询时,支持准备语句的数据库将自动执行此操作.

在python中,参数化查询如下所示:

cursor.execute("SELECT FROM tablename WHERE fieldname = %s", [value])
Run Code Online (Sandbox Code Playgroud)

根据您的驱动程序,参数化的具体样式可能会有所不同,您可以导入数据库模块然后执行print yourmodule.paramstyle.

来自PEP-249:

paramstyle

       String constant stating the type of parameter marker
       formatting expected by the interface. Possible values are
       [2]:

           'qmark'         Question mark style, 
                           e.g. '...WHERE name=?'
           'numeric'       Numeric, positional style, 
                           e.g. '...WHERE name=:1'
           'named'         Named style, 
                           e.g. '...WHERE name=:name'
           'format'        ANSI C printf format codes, 
                           e.g. '...WHERE name=%s'
           'pyformat'      Python extended format codes, 
                           e.g. '...WHERE name=%(name)s'
Run Code Online (Sandbox Code Playgroud)

  • 字符串是否会自动转义(使查询安全)? (5认同)
  • @scippie是的,没有.虽然您在技术上不需要担心转义,并且查询本质上是安全的,但这并不是因为参数被转义.原因是参数作为查询的元数据发送到服务器,而不是像查询语句一样,如果您正在进行天真的字符串连接.(如果您的数据库支持参数化查询,则为true;如果不支持,则python数据库模块使用强大的字符串连接来模拟它们) (4认同)
  • 我认为你指的是自动SQL引用,而不是实际的参数化查询. (3认同)
  • 似乎*MySQLdb*发送每个查询简单而没有"准备"(也在`executemany`中发送多个普通`execute`),而*oursql*执行`prepare`后跟`execute`(或`executemany`) ,只发送参数/值).https://launchpad.net/oursql (3认同)

Jam*_*hon 13

直接回答,不是没有.

joshperry的答案很好地解释了它的作用.

eugene回答类似的问题,

检查MySQLdb 包注释:

"参数化"是在MySQLdb中通过转义字符串然后盲目地将它们插入到查询中而不是使用MYSQL_STMT API来完成的.因此,unicode字符串必须经过两个中间表示(编码字符串,转义编码字符串)才能被数据库接收.

所以答案是:不,它没有.

  • 当你说"python"没有时,那不完全正确.MySQLdb模块不支持预处理语句,但是我们的mysql支持.https://launchpad.net/oursql/ (12认同)

shy*_*ent 10

快速浏览一下MySQLdb包的Cursor对象的execute()方法(我想是一种与mysql集成的事实包),似乎(至少在默认情况下)它只进行字符串插值引用而不是实际的参数化查询:

if args is not None:
    query = query % db.literal(args)
Run Code Online (Sandbox Code Playgroud)

如果这不是字符串插值,那么是什么?

在executemany的情况下,它实际上尝试将insert/replace作为单个语句执行,而不是在循环中执行它.这就是它,似乎没有魔法.至少不是默认行为.

编辑:哦,我刚刚意识到,模数运算符可以被覆盖,但我觉得自己喜欢作弊并且使用了源代码.mod但是,在任何地方都没有找到覆盖.


小智 5

如果您只关心性能,则使用Amit建议的SQL接口可以正常工作.但是,您将失去对SQL注入的保护,而本机Python对预准备语句的支持可能会带来这种保护.Python 3具有为PostgreSQL提供预处理语句支持的模块.对于MySQL,"oursql"似乎提供了真正准备好的语句支持(不像其他模块那样伪造).


fro*_*ega 5

对于那些想要解决这个问题的人来说,是的,你可以使用Python和MySQL的预处理语句.只需使用MySQL本身的MySQL Connector/Python并实例化正确的光标:

https://dev.mysql.com/doc/connector-python/en/index.html

https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursorprepared.html