【发布时间】:2019-12-19 17:35:01
【问题描述】:
我正在尝试使用 Python / Postgres 编写动态 SQL 命令。在我的 where 子句中,我想使用一个查询参数(它是用户定义的),它必须在代码列(varchar)中查找 NULL 值,但在其他情况下也可以查找特定数字。
如果我必须检查某个值,我会使用这个:
cursor.execute("""
select
z.code as code
from
s_order as o
LEFT JOIN
s_code as z ON o.id = z.id
where
z.code = %(own_id)s;
""", {
'own_id': entry
})
但是,如果我必须检查 NULL 值,SQL,更具体地说,WHERE 子句必须是
select
z.code as code
from
s_order as o
LEFT JOIN
s_code as z ON o.id = z.id
WHERE
z.code IS NULL;
第一个语句中使用的查询参数不适用于第二个语句,因为它只能替换等式右侧的值,而不能替换运算符。我在这里(https://realpython.com/prevent-python-sql-injection/#using-query-parameters-in-sql)读到,表名也可以使用 psycopg2 提供的 SQL 标识符替换,但无法找到如何替换整个 WHERE 子句或至少是运算符。
不幸的是,我无法更改代码列中的 NULL 值(例如,使用默认值),因为这些 NULL 值是通过 JOIN 操作创建的。
目前我唯一的选择是根据输入值进行不同的 SQL 查询,但由于 SQL 查询很长(我为这个问题缩短了它)而且我有很多类似的查询,它会导致很多类似的代码......那么我怎样才能让这个 WHERE 子句动态呢?
编辑: 除了标记为正确的答案之外,我还想添加自己的解决方案,它不是那么优雅,但在更复杂的场景中可能会有所帮助,因为 NULL 字段被替换为 COALESCE 的“默认”值:
create view orsc as
select
coalesce(z.code), 'default') as code
from
s_order as o
LEFT JOIN
s_code as z ON o.id = z.id;
SELECT
orsc.code as code2
from
orsc
WHERE
code2 = 'default'; //or any other value
EDIT2:查看标记答案的 cmets,为什么视图可能根本不需要。
EDIT3:这个question 没有帮助,因为它只要求检查NULL 值。除此之外,答案中显示的 IF 语句将大大增加我的整个代码库(每个查询都很长,并且经常以稍微适应的方式使用)。
【问题讨论】:
-
不,很遗憾没有。答案建议使用 IF 创建一个或另一个 SQL 命令,这是可行的,但如上所述对我来说并不理想。
-
@richyen 你能确认链接的讨论没有回答我的问题吗? SO 给了我一个方框,上面写着一个类似的问题可能会回答我的问题并且它不会消失。或者,我的问题可能会有所帮助......
标签: python sql postgresql psycopg2