SQL 标识符替换 - 使用列名列表

Posted

技术标签:

【中文标题】SQL 标识符替换 - 使用列名列表【英文标题】:SQL identifier substitution - Using a list of column names 【发布时间】:2021-11-02 15:38:06 【问题描述】:

我正在尝试运行表单的查询:

SELECT from TABLE where foo = VALUE

但我希望能够提供一个列表来替换

根据 psycopg 文档,为了安全地执行此操作,您需要使用 sql.Identifier 函数,以便正确转义参数,然后执行以下操作:

SQL = sql.SQL(
    "SELECT  FROM foo WHERE bar = %s"
).format(identifier)

cursor.execute(SQL, [VALUE])

identifier 是单个元素时,这有效,但我需要它是任意数字。例如,如果:

identifier = ["abc", "def"]

VALUE = 4

SQL = SELECT abc def FROM foo WHERE bar = 4

我已经尝试为identifier 的每个成员运行sql.Identifier(x),但这给出了"abc""def",这显然是不正确的。

【问题讨论】:

为什么这被标记为 Django?你不能用 Django-ORM 做到这一点吗? @Saturnix 因为是 django 的游标对象,但也没什么大不了的。很遗憾,我不能在这里使用 ORM。 【参考方案1】:

你需要使用sql.join(),让它像列表理解一样工作:

from psycopg2 import sql

cols = ["abc", "def"]
query = sql.SQL(
    "select 0 from 1 where abc = %s").format(
        sql.SQL(', ').join([sql.Identifier(c) for c in cols]),
        sql.Identifier('foo')
)
cur = conn.cursor()
print(query)
print(cur.mogrify(query, ('1', )))
cur.execute(query, ('1', ))
print (cur.rowcount, cur.fetchall())

输出:

Composed([SQL('select '), Composed([Identifier('abc'), SQL(', '), Identifier('def')]), SQL(' from '), Identifier('foo'), SQL(' where abc = %s')])
select "abc", "def" from "foo" where abc = '1'
(1, [('1', '2')])

【讨论】:

这会像这样转义列名:"foo",而不是 foo,postgres 似乎不喜欢这... 这行得通,只是编辑了答案。您收到任何错误吗? 错误是该列不存在。该查询在列名周围没有引号。

以上是关于SQL 标识符替换 - 使用列名列表的主要内容,如果未能解决你的问题,请参考以下文章

如何以编程方式确定哪些 SQL 表具有标识列

ora 00904标识符无效

ORA-00904: 标识符无效但表名和列名正确?

如何处理看起来像 SQL 关键字的 SQL 列名?

sql2005中设置字段属性时,如何设标识列(自增1)和必须唯一

Oracle SQL:在立即执行的内部循环中使用外部循环标识符