我是初学SQL用户。
我有一个包含三个表的数据库,表人和表酒店和公寓。每个人与一个酒店或公寓只有一个关系,但每个酒店或公寓可以分配一个或多个人。
拥有以下架构:
class Person(Base):
__tablename__ = 'person'
id = Column(Integer, primary_key=True, nullable=False)
person_name = Column(String, nullable=False)
status = Column(String, nullable=False)
class Hotel(Base):
__tablename__ = 'hotel'
id = Column(Integer, primary_key=True, nullable=False)
hotel_name = Column(String, nullable=False)
hotel_address = Column(String)
person_id = Column(Integer, ForeignKey("person.id"), nullable=False)
person = relationship("Person", backref=backref("hotel", uselist=False))
class Apartment(Base):
__tablename__ = 'apartment'
id = Column(Integer, primary_key=True, nullable=False)
apartment_address = Column(String, nullable=False)
person_id = Column(Integer, ForeignKey("person.id"), nullable=False)
person = relationship("Person", backref=backref("apartment", uselist=False))
或者这个,每个酒店和公寓都有一个唯一的密钥,并且过滤新的“密钥”栏:
class Person(Base):
__tablename__ = 'person'
id = Column(Integer, primary_key=True, nullable=False)
person_name = Column(String, nullable=False)
status = Column(String, nullable=False)
key = Column(String, nullable=False)
class Hotel(Base):
__tablename__ = 'hotel'
id = Column(Integer, primary_key=True, nullable=False)
hotel_name = Column(String, nullable=False)
hotel_address = Column(String)
key = Column(String, nullable=False, unique=True)
class Apartment(Base):
__tablename__ = 'apartment'
id = Column(Integer, primary_key=True, nullable=False)
apartment_address = Column(String, nullable=False)
key = Column(String, nullable=False, unique=True)
拥有唯一键时,酒店和公寓表中的列“id”是否不必要?
第二个问题是关于Person表中的这一列:
status = Column(String, nullable=False)
我想让状态栏只是(酒店,公寓)中的一个值,它可以告诉我们在酒店或公寓的表格中找到关系的确切位置。
有什么想法吗?
答案 0 :(得分:2)
在第一个示例中,person_id
和Hotel
表中有Apartment
个列,这意味着您将在Hotel
或Apartment
表中有单独的记录每个人,看起来不像你打算做的那样。因此,外键应移至Person
表。
因此,下一个问题是对两个表使用一个外键,这样您就不必进行繁琐的检查(例如检查设置apartment_id时是否设置了hotel_id)。这可以使用SqlAlchemy的polymorphic_identity
来完成。你可以阅读它here。在这种情况下,这是您的模型结构应该是什么样的:
class Person(Base):
__tablename__ = 'person'
id = Column(Integer, primary_key=True, nullable=False)
person_name = Column(String, nullable=False)
accommodation_id = Column(Integer, ForeignKey("accommodation.id"))
accommodation = relationship("Accommodation", backref="people")
class Accommodation(Base):
__tablename__ = 'accommodation'
__mapper_args__ = {
'polymorphic_identity':'accommodation',
# polymorphic_on determines the field that will have values like 'hotel' and 'apartment' depending on the table
'polymorphic_on': 'accommodation_type'
}
id = Column(Integer, primary_key=True)
accommodation_type = Column(String(32))
address = Column(String)
class Hotel(Accommodation):
__tablename__ = 'hotel'
__mapper_args__ = {
# all the records in this table will have accommodation_type = 'hotel'
'polymorphic_identity': 'hotel'
}
id = Column(Integer, ForeignKey('accommodation.id'), primary_key=True)
hotel_name = Column(String, nullable=False)
class Apartment(Accommodation):
__tablename__ = 'apartment'
__mapper_args__ = {
# all the records in this table will have accommodation_type = 'apartment'
'polymorphic_identity': 'apartment'
}
id = Column(Integer, ForeignKey('accommodation.id'), primary_key=True)
这样,您就拥有了基本模型Accommodation
,并且id
链接到表id
和Hotel
中的Appartment
列,这些列仅包含特定于他们的字段。 person.accommodation
将返回酒店或公寓,具体取决于实际值,并且父表和子表的所有属性都将可用。这样您就可以确保一个人不会被连接到酒店和公寓。您可以通过选中person.accommodation.accommodation_type
来查看此人的住宿类型。