一尘不染

在SQLAlchemy中,``过滤器''与``填充和过滤器''语法之间有什么区别?

sql

更具体地说,我看到很多人没有使用SQLAlchemy中的类似SQL的自然联接语法,而是倾向于将过滤器用于联接目的。要详细说明以下是我如何加入联接的方法:

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

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

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

(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的CPU和RAM的压力更大,而对本地计算机的压力更小,反之亦然)?

另外,前一种方法不允许update()Query API上的方法-即使无法只更新一个表,它也会抱怨不允许多表更新。后者允许update()正常工作。


阅读 207

收藏
2021-05-30

共1个答案

一尘不染

主要区别在于,前者会导致查询使用SQL-92
JOIN语法,而后者会使用较旧的语法-
例如,有些人出于习惯而不喜欢它。两者都是正确的方法,两者都与是否使用Python语言无关。我还认为,SQLAlchemy也不是惯用语言,但Query.join()正如您所指出的那样,它与定义的外键关系和ORM关系很好地配合使用。在现代SQL
DBMS中,它们还应导致相同的执行计划,因此资源使用等方面没有有意义的区别。

关于Query.update()不支持显式联接的问题,不同的SQL
DBMS对具有不同语法和方法的多个表更新具有不同的支持。有些允许显式连接,有些则不允许,有些则允许通过子查询进行更新。当前的实现似乎是一个折衷方案,并且将为UPDATE使用中的DBMS提供适当的声明。

2021-05-30