在 SQLAlchemy 中,“过滤器”与“连接和过滤器”语法有啥区别?

Posted

技术标签:

【中文标题】在 SQLAlchemy 中,“过滤器”与“连接和过滤器”语法有啥区别?【英文标题】:In SQLAlchemy what is the difference between the "filter" vs "join and filter" syntax?在 SQLAlchemy 中,“过滤器”与“连接和过滤器”语法有什么区别? 【发布时间】:2019-05-01 02:12:00 【问题描述】:

更具体地说,我看到很多人没有在 SQLAlchemy 中使用自然的类似 SQL 的连接语法,而是倾向于使用过滤器来进行连接。在这里详细说明我将如何加入:

(session.Query(Book)
        .join(Author, Publisher, Retailer)
        .filter(
            Author.name == "Crenshaw Adams",
            Publisher.country == "United States",
            Retailer.is_online == True))

连接列隐含在模型声明文件中定义的关系中。

但在其他任何地方(尤其是在 *** 上)我都看到人们这样做:

(session.Query(Book)
        .filter(
            Book.author_id == Author.id,
            Author.publisher_id == Publisher.id,
            Publisher.retailer_id == Retailer.id,
            Author.name == "Crenshaw Adams",
            Publisher.country == "United States",
            Retailer.is_online == True
            ))

以下哪种方法是正确的方法?哪个更 Pythonic?或者,至少,应该使用 SQLAlchemy 的方式更惯用?并且在DB资源使用方面,还是本地机器资源使用方面有区别(即DB的CPU和RAM压力更大,本地机器压力更小,反之亦然)?

此外,前一种方式不允许查询 API 上的 update() 方法 - 它抱怨不允许多表更新 - 即使我只更新一个表。后者允许update() 正常工作。

【问题讨论】:

【参考方案1】:

主要区别在于前者导致查询使用SQL-92JOIN 语法,而后者使用较旧的语法——例如,有些人出于习惯更喜欢它。两者都是正确的方法,并且与代码是否为 Pythonic 没有太大关系。同样在我看来,SQLAlchemy 中两者都不是更惯用的,尽管Query.join() 可以很好地与定义的外键关系和 ORM 关系配合使用,正如您自己所指出的那样。它们还应该在现代 SQL DBMS 中产生相同的执行计划,因此在资源使用等方面没有有意义的差异。

至于Query.update()不支持显式连接,不同的SQL DBMS对多表更新的支持不同,语法和方法也不同。有些允许显式连接,有些不允许,还有some allow updating through subqueries。当前的实现似乎是一种折衷方案,并将呈现给正在使用的 DBMS 的合适的 UPDATE 语句。

【讨论】:

以上是关于在 SQLAlchemy 中,“过滤器”与“连接和过滤器”语法有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

SQLAlchemy:如何在连接查询中的过滤器之前应用 distinct

如何在 sqlalchemy 查询过滤器中使用用户定义的 python 函数?

使用 Flask、SqlAlchemy 和 Jinja2 在 ORM 中引用过滤器项

如何将自动过滤器添加到与 SQLAlchemy 的关系中?

对象上的 Sqlalchemy 过滤器

sqlalchemy 过滤多列