没有外键约束的联接

时间:2019-12-03 12:05:37

标签: python sql join sqlalchemy

我试图在两个表之间执行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)))

1 个答案:

答案 0 :(得分: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)