简体   繁体   English

为什么 psycopg2 cursor.execute() 和 SQL 查询参数会导致语法错误?

[英]Why does psycopg2 cursor.execute() with SQL query parameter cause syntax error?

When specifying a parameter to execute() in psycopg2 in Python, like this:在 Python 中的 psycopg2 中为 execute() 指定参数时,如下所示:

cursor.execute('SELECT * FROM %s', ("my_table", ))

I'm getting this error:我收到此错误:

psycopg2.ProgrammingError: syntax error at or near "'my_table'"
LINE 1: SELECT * FROM 'my_table'

What am I doing wrong?我究竟做错了什么? It looks like psycopg2 is adding single quotes to the query, and those single quotes are causing the syntax error.看起来 psycopg2 正在向查询中添加单引号,而这些单引号导致语法错误。

If I don't use a parameter, it works correctly:如果我不使用参数,它可以正常工作:

cursor.execute('SELECT * FROM my_table')

I believe that parametrized statements like this are meant to be used with values and not table names (or SQL keywords, etc.). 我相信这样的参数化语句应与一起使用,而不是与表名(或SQL关键字等)一起使用。 So you're basically out of luck with this. 因此,您基本上没有运气。

However, do not worry, as this mechanism is meant to prevent SQL injection, and you normally know what table you want to access at code-writing time, so there is little chance somebody may inject malicious code. 但是,请不要担心,因为该机制旨在防止SQL注入,并且您通常在代码编写时就知道要访问哪个表,因此几乎没有人可能注入恶意代码。 Just go ahead and write the table in the string. 只需将表写入字符串即可。

If, for some (possibly perverse) reason you keep the table name parametric like that: 如果出于某些(可能是不正确的)原因,您将表名保留为参数形式,例如:

  1. If the table name comes from your program (eg a dictionary, or class attribute), then do the usual string substitution. 如果表名来自您的程序(例如,字典或类属性),请执行通常的字符串替换。
  2. If the table name comes from the external world (think "user input"): either don't do that, or trust the user completely and apply the previous approach 1. 如果表名来自外部世界(请考虑“用户输入”):要么不这样做,要么完全信任用户并采用前面的方法1。

For example: 例如:

cursor.execute(
    'SELECT * FROM %s where %s = %s'
    % ("my_table", "colum_name", "%s"), #1
    ("'some;perverse'string;--drop table foobar")) #2

#1 : Let the third %s be replaced with another '%s' at this time, to allow later processing by psycopg2 #2 : This is the string that will be properly quoted by psycopg2 and placed instead of that third '%s' in the original string #1 :此时将第三个%s替换为另一个'%s',以允许psycopg2稍后进行处理#2 :这是将被psycopg2正确引用并代替第三个'%s'放置的字符串在原始字符串中

cur.execute(
    """
    SELECT * FROM %s;
    """,
    {"my_table",}
)
conn.commit()

A bit late to this question, but there is functionality within Psycopg2 that supports this use case via SQL String Composition .这个问题有点晚了,但是 Psycopg2 中有一些功能通过SQL String Composition支持这个用例。 This approach provides a way to "generate SQL dynamically, in a convenient and safe way."这种方法提供了一种“以方便和安全的方式动态生成 SQL”的方法。

In the use case in the original answer:在原始答案的用例中:

cursor.execute(
    sql.SQL("SELECT * FROM {}").format(
        sql.Identifier("my_table")))

Using SQL String Composition is a much safer approach than string parameter interpolation via % discussed in Irfy's answer.使用 SQL 字符串组合比通过 Irfy 的回答中讨论的%字符串参数插值更安全。 As noted in the psycopg2 documentation :正如psycopg2 文档中所述

Warning Never, never, NEVER use Python string concatenation (+) or string parameters interpolation (%) to pass variables to a SQL query string.警告 永远,永远,永远不要使用 Python 字符串连接 (+) 或字符串参数插值 (%) 将变量传递给 SQL 查询字符串。 Not even at gunpoint.甚至不是在枪口下。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM