where() 不按 sqlalchemy 中的预期处理参数

Posted

技术标签:

【中文标题】where() 不按 sqlalchemy 中的预期处理参数【英文标题】:where() does not process parameters as expected in sqlalchemy 【发布时间】:2018-09-18 22:26:20 【问题描述】:
table = engine.getFTable();
dBtable = table; 
query = select([dBtable.c.id]).where( dBtable.c.FName == 'F1' );
print(query);

这得到了正确的表,但由于某种原因,构造的查询不是人们所期望的。以下是构造的查询

SELECT "FList".id 
FROM "FList" 
WHERE "FList"."FName" = ?

而不是

SELECT "FList".id 
FROM "FList" 
WHERE "FList"."FName" = 'F1'

【问题讨论】:

【参考方案1】:

SQLAlchemy 尽可能创建parameterized SQL queries。

这意味着您的查询中的? WHERE 子句只是一个占位符,在执行查询时将用实际数据 ('F1') 填充(然后将参数绑定 到查询)。

确切的syntax of the bound parameter placeholder 取决于您使用的 SQL 方言(PostgreSQL、mysql、...)。有些使用?,有些支持:user_id等命名参数。

您可以通过编译该查询对象并显示它的参数来查看将要填写的参数:

>>> query = select([table.c.userid]).where(table.c.userid == 'lukas.graf')
>>> print query
SELECT users.userid
FROM users
WHERE users.userid = :userid_1            <---- bind parameter placeholder

>>> compiled = query.compile()
>>> print compiled.params
u'userid_1': 'lukas.graf'

SQLAlchemy documentation 解释了如何将 SQL 表达式呈现为字符串,如果您需要调试它们:

>>> from sqlalchemy.dialects import postgresql
>>>
>>> query = select([table.c.userid]).where(table.c.userid == 'lukas.graf')
>>> compiled = query.compile(dialect=postgresql.dialect(), compile_kwargs="literal_binds": True)
>>> print compiled
SELECT users.userid
FROM users
WHERE users.userid = 'lukas.graf'

还要注意该文档中的段落:

上述表格将在传递给 Python DBAPI,其中包括未呈现绑定参数 排队。 SQLAlchemy 通常不会对绑定参数进行字符串化,因为 这由 Python DBAPI 适当处理,更不用说 绕过绑定参数可能是最广泛利用的 现代 Web 应用程序中的安全漏洞。

意思是,参数化查询以及单独绑定到它的参数,将像这样传递给 Python DBAPI(如果您愿意的话,是 DB“驱动程序”),因为这是最高效和最安全的方式做事。您可以使用如上所示的内联参数来可视化查询,但这并不是真正的实际情况。


相反,如果您正在调试您的查询,您更应该使用echo=True parameter for the engine:这将方便地记录参数化查询在执行时,它们的绑定参数。

【讨论】:

以上是关于where() 不按 sqlalchemy 中的预期处理参数的主要内容,如果未能解决你的问题,请参考以下文章

SQLAlchemy - WHERE 子句中的子查询

SQLAlchemy 更新多个 WHERE 条件

Laravel路线,其中where子句不按预期工作

使用 sqlalchemy 查询使用多列 where in 子句

SQLAlchemy中的可选参数

SQLAlchemy Left join WHERE 子句被转换为零和一