目录
SQLAlchemy关联表
常用的级联选项
外键
SQLAlchemy关联表
SQLAlchemy 是一个 Python 的 ORM(对象关系映射)库,它允许你在 Python 中使用类来表示数据库中的表,从而更方便地进行数据库操作。在 SQLAlchemy 中,可以使用关联表(relationship)来定义两个表之间的关系,包括一对一、一对多和多对多等关系。
在定义关联表的时候,你可以设置 cascade
参数来指定在删除记录时的级联行为。
常用的级联选项
all
:删除主记录时,从属记录也会被删除。save-update
:当主记录发生变化时,从属记录会自动保存。delete-orphan
:删除主记录时,从属记录也会被删除,如果从属记录变成了孤儿(没有任何主记录与之关联),也会被删除。
以下是一个简单的例子,演示了如何在 SQLAlchemy 中设置关联表的删除策略:
from sqlalchemy import create_engine, Column, Integer, String, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationshipBase = declarative_base()class Parent(Base):__tablename__ = 'parents'id = Column(Integer, primary_key=True)name = Column(String)children = relationship('Child', back_populates='parent', cascade='all, delete-orphan')class Child(Base):__tablename__ = 'children'id = Column(Integer, primary_key=True)name = Column(String)parent_id = Column(Integer, ForeignKey('parents.id'))parent = relationship('Parent', back_populates='children')# 创建数据库连接
engine = create_engine('sqlite:///example.db')# 创建表格
Base.metadata.create_all(engine)
Parent
表中有一个名为children
的关联关系,它关联到了Child
类,通过back_populates
参数指定了反向关系的属性名为parent
,并且设置了级联删除策略为all, delete-orphan
,这表示在删除父记录时,会级联删除子记录,并且也会删除变成孤儿的子记录。
Child
表中有一个名为parent
的关联关系,它关联到了Parent
类,通过back_populates
参数指定了反向关系的属性名为children
。创建了一个 SQLite 数据库连接,并使用
Base.metadata.create_all(engine)
来创建表格。
外键
使用SQLAlchemy创建外键非常简单。在从表中增加一个字段,指定这个字段外键的是哪个表的哪个字段就可以了。从表中外键的字段,必须和主表的主键字段类型保持一致。
class User(Base):__tablename__ = 't_user'id = Column(Integer,primary_key=True,autoincrement=True)uname = Column(String(50),nullable=False,name='name')class News(Base):__tablename__ = 't_news'id = Column(Integer,primary_key=True,autoincrement=True)title = Column(String(50),nullable=False)content = Column(Text,nullable=False)uid = Column(Integer,ForeignKey('t_user.id',)
外键约束有以下几项:
-
RESTRICT:若子表中有父表对应的关联数据,删除父表对应数据,会阻止删除。默认项
-
NO ACTION:在MySQL中,同RESTRICT。
-
CASCADE:级联删除。
-
SET NULL:父表对应数据被删除,子表对应数据项会设置为NULL。
from sqlalchemy import Column,Integer,String,Text,ForeignKeyfrom db_util import Base,Sessionclass User(Base):__tablename__ = 't_user'id = Column(Integer,primary_key=True,autoincrement=True)uname = Column(String(50),nullable=False,name='name')class News(Base):__tablename__ = 't_news'id = Column(Integer,primary_key=True,autoincrement=True)title = Column(String(50),nullable=False)content = Column(Text,nullable=False)# uid = Column(Integer,ForeignKey('t_user.id')) # 默认不让删主表数据# uid = Column(Integer,ForeignKey('t_user.id',ondelete = 'RESTRICT')) # 默认的策略# uid = Column(Integer,ForeignKey('t_user.id',ondelete = 'NO ACTION')) # 默认的策略# uid = Column(Integer,ForeignKey('t_user.id',ondelete = 'CASCADE')) # 级联删除,发主表的数据被删除,子表的里数据也会删除uid = Column(Integer,ForeignKey('t_user.id',ondelete = 'SET NULL')) # 发现主表数据被删除时,子表的数据列会清空def create_data():user = User(uname = 'sxt') news1 = News(title='python',content='flask',uid = 1)news2 = News(title='MySQL',content='SQL',uid = 1)with Session() as ses:ses.add(user)ses.commit()with Session() as ses:ses.add(news1)ses.add(news2)ses.commit()if __name__ == '__main__':Base.metadata.create_all()create_data()
在
News
表中,使用了外键uid
关联到了t_user.id
,并设置了删除策略为SET NULL
,这表示当t_user
表中的对应记录被删除时,会将News
表中对应的外键字段(即uid
)设为NULL
。提供了一个
create_data
函数来创建用户和新闻的示例数据,并在__main__
中调用了该函数。在
create_data
函数中,首先创建了一个用户(uname 为 'sxt'),然后创建了两条新闻记录,并分别将uid
设置为 1,表示这两条新闻属于用户 1。然后你通过
Session
来提交了这些数据。最后,在
__main__
中调用了Base.metadata.create_all()
来创建数据库表结构,然后调用了create_data()
函数来插入示例数据。