【问题标题】:Join without foreign key constraint无外键约束加入
【发布时间】:2020-03-28 02:50:18
【问题描述】:

我正在尝试在两个表之间执行 JOIN,为此我用primaryjoin 属性描述了关系。我预计它将用于构建查询,但事实并非如此,并且sqlalchemy.exc.NoForeignKeysError: Can't find any foreign key relationships 失败。以下是重现错误所需的全部代码。请建议我如何描述我的表以及在这些表之间必须没有 ForeignKey 约束的情况下如何构造查询:

from sqlalchemy import Column, Integer, String, MetaData
from sqlalchemy import create_engine
from sqlalchemy.sql import select, insert
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship


METADATA = MetaData()
SQLAlchemyTable = declarative_base(metadata=METADATA)


class Cities(SQLAlchemyTable):
    __tablename__ = 'cities'

    id = Column(Integer, primary_key=True)
    name = Column(String, unique=True)


class Orders(SQLAlchemyTable):
    __tablename__ = 'orders'

    id = Column(Integer, primary_key=True)
    city_id = Column(Integer, nullable=True)

    # relation creation code is taken from 
    # https://stackoverflow.com/questions/37806625/sqlalchemy-create-relations-but-without-foreign-key-constraint-in-db
    city = relationship(
        'Cities',
        foreign_keys=[city_id],
        primaryjoin='Orders.city_id==Cities.id'
    )


if __name__ == '__main__':
    connection_string = 'sqlite:///test_join.db'
    db = create_engine(connection_string)
    METADATA.drop_all(db)
    METADATA.create_all(db)
    db.execute(insert(Cities).values([{'id': 1, 'name': 'city_name_1'}]))
    db.execute(insert(Cities).values([{'id': 2, 'name': 'city_name_2'}]))
    db.execute(insert(Orders).values([{'id': 1, 'city_id': 1}]))
    db.execute(insert(Orders).values([{'id': 2, 'city_id': None}]))
    db.execute(insert(Orders).values([{'id': 3, 'city_id': 3}]))
    # i need to get this query:
    print(list(db.execute('SELECT orders.id, orders.city_id FROM orders JOIN cities ON orders.city_id = cities.id WHERE cities.id = 1')))
    # how?
    query = select([Orders]).join(Cities).where(Cities.id == 1)  # not working
    print(query)
    print(list(db.execute(query)))

【问题讨论】:

    标签: python sql join sqlalchemy


    【解决方案1】:

    relationship 是一个 ORM 构造,但您正在使用 Core 来构建您的查询。您必须明确定义如何在两者之间加入:

    query = select([Orders]).\
        select_from(join(Orders, Cities, Orders.city_id == Cities.id)).\
        where(Cities.id == 1)
    

    注意使用Select.select_from()join() 而不是select([...]).join()。如果使用Query API,您可以根据关系定义连接:

    query = session.query(Orders).\
        join(Orders.city).\
        filter(Cities.id == 1)
    

    【讨论】:

    • session.query 是我一直在寻找的:一种使用所描述关系的方法。该死的,有不止一种方法来构建查询使 sqlalchemy 太复杂了。我刚开始使用这个库,但我已经讨厌它了。
    • 它在某种程度上是 2 个库合二为一,并且 ORM 构建在 Core 之上,因此它们可以很好地配合。
    • 您之前的评论较长:) 无论如何,感谢您的回复。
    • 是的,事后看来它有点居高临下,所以我想我会删除它。
    猜你喜欢
    • 2020-09-26
    • 2020-09-12
    • 2017-07-16
    • 2013-03-10
    • 2021-11-05
    • 2018-02-13
    • 2018-05-16
    相关资源
    最近更新 更多