在SQLAlchemy中,“过滤器”与“连接和过滤器”语法之间有什么区别?

时间:2018-11-29 04:26:22

标签: python sql postgresql sqlalchemy

更具体地说,我看到很多人不使用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的压力较大,而对本地计算机的压力较小,反之亦然)?

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

1 个答案:

答案 0 :(得分:2)

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

对于Query.update()不支持显式连接的情况,不同的SQL DBMS对不同表的支持不同,语法和方法也不同。有些允许显式联接,有些不允许,some allow updating through subqueries。当前的实现似乎是一个折衷方案,它将为正在使用的DBMS提供适当的UPDATE语句。