【问题标题】:sqlalchemy joinedload query can not make countingsqlalchemyjoinedload查询无法计数
【发布时间】:2016-05-06 15:05:50
【问题描述】:

我有两张桌子table_atable_btable_b.code_btable_a 的外键

table_a
code_a, val
-----------
aaa,100

table_b
code_b, name
------------
aaa, name1

我想通过加入两个表来得到这个结果:

table_result
code_a,val,name
---------------
aaa,100,name1

以下是Python代码:

class A(db.Model):
    __tablename__ = 'table_a'
    code_a = Column(String(20), ForeignKey("table_b.code_b"), primary_key=True)
    val = Column(Float)
    b = relationship("B", backref=backref('table_b'))


class B(db.Model):
    __tablename__ = 'table_b'
    code_b = Column(String(20), primary_key=True)
    name = Column(String(100))
    a = relationship("A", backref="table_a")

where_str = "code_b='aaa'"
q = A.query.options(joinedload_all(A.b)).filter(text(where_str))

rows1 = [i.serialize for i in q.all()] # CORRECT
rows2 = [i.serialize for i in q.paginate(1,10,False)] # ERROR

如果我只是查询所有得到rows1,这是正确的结果。但是,运行rows2 时会出错: DatabaseError: (cx_Oracle.DatabaseError) ORA-00904: "code_b"

我通过打印 SQL 语句来调试此错误:

SELECT count(*) AS count_1
FROM (SELECT "table_a".code_a AS "table_a_code_a", 
FROM "table_a"
WHERE code_b = 'aaa') anon_1

很明显,两个表连接。

但是,如果只是q.all(),SQL 语句将是:

SELECT "table_a".code_a AS "table_a_code_a", 
FROM "table_a" LEFT JOIN "table_b"
WHERE code_b = 'aaa'

这是正确的。

那么,如何在进行分页时获得正确的结果。


EDIT1:

问:为什么我使用where_str

A:在 HTML 页面中,我使用查询生成器(http://querybuilder.js.org/)来获取查询过滤器(可能很复杂)。因此,传递给 SQLAlchemy 查询文件管理器很方便。

有没有更好的方法来实现这一点?


EDIT2: 解决方案:

q = A.query.join(A.b).options(contains_eager(A.b)).filter(text(where_str))

【问题讨论】:

    标签: python sqlalchemy flask-sqlalchemy


    【解决方案1】:

    这是不正确的:

    where_str = "code_b='aaa'"
    q = A.query.options(joinedload_all(A.b)).filter(text(where_str))
    

    SQLAlchemy 应该如何知道您的 where_str 中的 code_b 应该引用表 B?

    试试:

    q = A.query.join(A.b).filter(B.code_b == "aaa")
    

    如果您还需要执行joinedload,请执行以下操作:

    q = A.query.join(A.b).options(contains_eager(A.b)).filter(B.code_b == "aaa")
    

    【讨论】:

    • @seizetheday 仅仅因为您需要从前端传入过滤器并不意味着您需要使用text 构造。无论如何,您使用 text 构造本身并不是问题;问题是您使用joinedload 而不是.join
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多