【问题标题】:SQLAlchemy Generates Wrong SQL (for aliased and self-join)?SQLAlchemy 生成错误的 SQL(用于别名和自联接)?
【发布时间】:2013-10-11 09:52:01
【问题描述】:

SQLAlchemy 0.8 为以下简单的自连接生成错误的 SQL --

class ScheduledJob(Base):
    Id = Column('Id', Integer, primary_key=True)
    DependentJob1 = Column('DependentJob1', Integer)

DJ1 = aliased(ScheduledJob)
query = dbsession.query(ScheduledJob.Id, DJ1.Id).outerjoin(
        DJ1, ScheduledJob.DependentJob1==DJ1.Id)
print query

并打印错误的 SQL --

SELECT "ScheduledJob"."Id" AS "ScheduledJob_Id"
FROM "ScheduledJob" LEFT OUTER JOIN "ScheduledJob" AS "ScheduledJob_1" ON
"ScheduledJob"."DependentJob1" = "ScheduledJob"."Id"

虽然应该是——

SELECT "ScheduledJob"."Id" AS "ScheduledJob_Id",
"ScheduledJob_1"."Id" AS "ScheduledJob_1_Id"
FROM "ScheduledJob" LEFT OUTER JOIN "ScheduledJob" AS "ScheduledJob_1" ON
"ScheduledJob"."DependentJob1" = "ScheduledJob_1"."Id"

更令人费解的是,我按照 SQLAlchemy 文档尝试的所有独立别名/连接/自连接测试都可以正常工作。

可能出了什么问题?任何指针将不胜感激。

顺便说一句,我在映射多个数据库,会不会和这个问题有关?

【问题讨论】:

    标签: python sql orm sqlalchemy


    【解决方案1】:

    无法复制。测试用例在 0.8.2、0.8.1、0.8.0 上运行,结果正确:

    from sqlalchemy import *
    from sqlalchemy.orm import *
    from sqlalchemy.ext.declarative import declarative_base
    
    Base = declarative_base()
    
    class ScheduledJob(Base):
        __tablename__ = 'ScheduledJob'
    
        Id = Column('Id', Integer, primary_key=True)
        DependentJob1 = Column('DependentJob1', Integer)
    
    session = Session()
    
    DJ1 = aliased(ScheduledJob)
    query = session.query(ScheduledJob.Id, DJ1.Id).outerjoin(DJ1, ScheduledJob.DependentJob1==DJ1.Id)
    print query
    

    输出:

    SELECT "ScheduledJob"."Id" AS "ScheduledJob_Id", "ScheduledJob_1"."Id" AS "ScheduledJob_1_Id" 
    FROM "ScheduledJob" LEFT OUTER JOIN "ScheduledJob" AS "ScheduledJob_1" ON "ScheduledJob"."DependentJob1" = "ScheduledJob_1"."Id"
    

    我怀疑在您的实际应用中,“DJ1”实际上并不是 ScheduledJob 的别名。

    【讨论】:

    • 非常感谢您抽出宝贵的时间,迈克!无法重现这种神秘的行为正是我无法拿出一个完整的测试来展示这个问题的原因——让我把整个星期天的时间都投入进去,看看我是否能找到更多的线索。但至少 sn-p 是从源代码中提取的文字,“DJ1”实际上是 ScheduledJob 的别名。
    【解决方案2】:

    问题是由于 SQLAlchemy 使用不正确造成的,它映射了从同一个 Base 扩展的多个表并具有相同的 __tablename__

    一旦我将它们分开到不同的 Base 上,一切正常 --

    class ScheduledJobMixin(object):
        Id = Column('Id', Integer, primary_key=True)
        ...
    
    Remote_Base = declarative_base()
    class RemoteScheduledJob(ScheduledJobMixin, Remote_Base):
        __tablename__ = 'ScheduledJob'
    
    Base = declarative_base()
    class ScheduledJob(ScheduledJobMixin, Base):
        __tablename__ = 'ScheduledJob'
    

    【讨论】:

    • 非常感谢我遇到了同样的问题;)我需要动态创建对象type (...),然后使用不同的declerative Base 在此表上进行自联接,问题就消失了。跨度>
    猜你喜欢
    • 2013-03-23
    • 2021-09-17
    • 1970-01-01
    • 2012-01-21
    • 2013-10-04
    • 1970-01-01
    • 2019-09-26
    • 2012-08-17
    • 1970-01-01
    相关资源
    最近更新 更多