资讯专栏INFORMATION COLUMN

Python-SQLAlchemy:第4节:级联

henry14 / 3344人阅读

摘要:上一篇文章第节关系操作级联是在一对多关系中父表与子表进行联动操作的数据库术语。注意级联独立于本身针对外键的级联定义。代码执行后数据库表中的内容的变化表五年二班理想路号楼表理想男静安区女静安区小马哥女闸口区张三韩永跃男静安区

上一篇文章:Python-SQLAlchemy:第3节:关系操作

级联是在一对多关系中父表与子表进行联动操作的数据库术语。因为父表与子表通过外键关联,所以对父表或子表的增、删、改操作会对另一张表产生相应的影响。适当的利用级联可以开发出更优雅、健壮的数据库程序。本节学习SQLAlchemy中级联的操作方法。

注意:SQLAlchemy级联独立于SQL本身针对外键的级联定义。即使在数据库表定义中没有定义on delete等属性,也不影响开发者在SQLAlchemy中使用级联。
1、级联定义

SQLAlchemy中的级联通过对父表中的relationship属性定义cascade参数来实现,代码如下:

from sqlalchemy import Table,Column,Integer,ForeignKey,String
from sqlalchemy.orm import relationship,backref
from sqlalchemy.ext.declarative import declarative_base

Base=declarative_base()

class Class(Base):
    __tablename__="class"
    class_id=Column(Integer,primary_key=True)
    name=Column(String(50))
    level=Column(Integer)
    address=Column(String(50))

    students=relationship("Student",backref="class_",cascade="all")

class Student(Base):
    __tablename__="student"
    student_id=Column(Integer,primary_key=True)
    name=Column(String(50))
    age=Column(Integer)
    gender=Column(String(10))
    address=Column(String(50))
    class_id=Column(Integer,ForeignKey("class.class_id"))

上述代码定义了班级表Class(父表)和学生表Student(子表)。一对多的关系有父表中的relationship属性students进行定义。relationship中的cascade参数定义了要在该关系上实现的级联方法为:all。

SQLAlchemy中另外一种设置级联的方式是在子表的relationship的backref中进行设置。比如上述代码可以写为如下形式,意义保持不变:

from sqlalchemy import Table,Column,Integer,ForeignKey,String
from sqlalchemy.orm import relationship,backref
from sqlalchemy.ext.declarative import declarative_base

Base=declarative_base()

class Class(Base):
    __tablename__="class"
    class_id=Column(Integer,primary_key=True)
    name=Column(String(50))
    level=Column(Integer)
    address=Column(String(50))
class Student(Base):
    __tablename__="student"
    student_id=Column(Integer,primary_key=True)
    name=Column(String(50))
    age=Column(Integer)
    gender=Column(String(10))
    address=Column(String(50))
    class_id=Column(Integer,ForeignKey("class.class_id"))
    class_=relationship("Class",backref="students",cascade="all")

上述代码没有在父表Class中设置relationship和cascade,而是在子表中设置了。

SQLAlchemy中可选的cascade取值范围如下表所示:

可选值 意义
save-update 当一个父对象被新增到session中时,该对象当时关联的子对象也自动被新增到session中。
merge Session.merge是一个对数据库对象进行新增或更新的办法。cascade取值为merge时的意义为:当父对象进行merge操作时,该对象当时关联的子对象也会被merge
expunge Session.expunge是一种将对象从session中移除的方法。cascade取值为expunge时的意义为:当父对象进行了expunge操作时,该对象当时关联的子对象也会被从session中删除。
delete 当父对象被delete时,会自动将该子对象删除
delete-orphan 当子对象不再与任何父对象关联时,会自动将该子对象删除
refresh-expire Session.expire是一种设置对象已过期、下次引用时需要从数据库即时读取的方法。cascade取值为refredh-expire时的意义为:当父对象进行了expire操作时,该对象当时关联的子对象也进行expire操作。
all 是一个集合值,表示:save-update、merge、refresh-expire、expunge、delete同时被设置

多个cascade属性可以通过逗号分隔并同时赋值给cascade。例如:

students=relationship("Student",backref="class_",cascade="save-update,merge,expunge")

在默认情况下,任何relationship的级联属性都被设置为cascade="save-update,merge"。下面就常用的参数:save-update、delet、delete-orphan的功能进行举例说明。

2、save-update级联

save-update级联是指当一个父对象被新增到session中时,该对象当时关联的子对象也自动被新增到session中。

通过如下代码建立一个父对象class和两个子对象students1与students2

class_=Class()
student1,student2=Student(),Student()
class_.students.append(student1)
class_.students.append(student2)

如果父子级联关系包含save-update,则只需要将父对象保存到session中,子对象会自动被保存。

session.add(class_)
if student1 in session:
    print("The student1 has been added too!")

上面代码将会打印:"The student1 has been added too!"

技巧:”in“语句可以判断某对象是否被关联到了session中。已被关联的对象在session被commit时会被写入到视频库中。

即使父对象已经被新增到session中,新关联的子对象仍然可以被添加:

class_=Class()
session.add(class_)
students3=Student()
if student3 in session:
    print("The student3 is added before append to the class_!")
class_.students.append(students)
if student1 in session:
    print("The student3 is added after append to the class_!")

这段代码打印”The student3 is added after append to the class_!“

3、delete级联

顾名思义,delete级联是指当父对象被从session中删除时,其关联的子对象也自动被从session中delete。通过一个例子演示delete的作用,假设数据库中class表和students表的内容如下表所示:

class表:

class_id name level address
1 三年二班 3 理想路520号1楼
2 五年一班 5 理想路520号3楼
3 五年二班 5 理想路520号3楼

student表:

student_id class_id name age gender address contactor
1 1 理想 10 静安区 Null
2 1 mark 10 静安区 Null
3 1 小马哥 9 闸口区 张三
4 2 张苗 10 宝山区 NULL
5 2 小黑 12 静安区 李四
6 2 喵喵 11 闸北区 NULL
7 1 韩永跃 10 静安区 NULL
8 3 小镜镜 12 闸北区 NULL
9 3 小镜子 12 宝山区 NULL

从例表中可知,系统中有3个班级,他们分别有4、3、2个学生。如果SQLAlchemy中没有把它们的relationship的cascade设置为delete,则删除父表内容不会删除相应的子表内容,而是把子表的相应外键设置为空。比如:

class_=session.query(Class).filter(name="三年二班").first() #三年二班的class_id为1
session.delete(class_) #删除class_id为1的班级

当cascade不包含delete时,上述代码中的delete语句相当于执行了如下SQL语句:

UPDATE student SET class_id=None WHERE class_id=1;
DELETE FROM class WHERE class_id=1;
COMMIT;

执行后数据表class和student的内容变化如下所示:

class表:

class_id name level address
2 五年一班 5 理想路520号3楼
3 五年二班 5 理想路520号3楼

student表:

student_id class_id name age gender address contactor
1 NULL 理想 10 静安区 Null
2 NULL mark 10 静安区 Null
3 NULL 小马哥 9 闸口区 张三
4 2 张苗 10 宝山区 NULL
5 2 小黑 12 静安区 李四
6 2 喵喵 11 闸北区 NULL
7 1 韩永跃 10 静安区 NULL
8 3 小镜镜 12 闸北区 NULL
9 3 小镜子 12 宝山区 NULL

此时将表定义中的relationship的cascade属性设置为delete:

students=relationship("Student",backref="class",cascade="delete")

现在通过如下语句删除“五年一班”:

class_=session.query(Class).filter(name="五年一班").first() #五年一班的class_id为2
session.delete(class_) #删除class_id为2的班级

当cascade包含“delete”时,上述代码中的delete语句相当于执行了如下SQL语句:

DELETE FROM student WHERE class=2;
DELETE FROM class WHERE class=2;
COMMIT;

执行后数据库表class和student的内容变化如下表所示:

class表:

class_id name level address
3 五年二班 5 理想路520号3楼

student表:

student_id class_id name age gender address contactor
1 NULL 理想 10 静安区 Null
2 NULL mark 10 静安区 Null
3 NULL 小马哥 9 闸口区 张三
7 NULL 韩永跃 10 静安区 NULL
8 3 小镜镜 12 闸北区 NULL
9 3 小镜子 12 宝山区 NULL
4、delete-orphan级联

delete-orphan级联是指当子对象不再与任何父对象关联时,会自动将该子对象删除。设置父表与子表的relationship中的cascade包含“delete-orphan”:

students=relationship("Student",backref="class",cascade="delete-orphan")

通过如下代码将于班级“五年一班”关联的学生全部脱离:

class_=session.query(Class).filter(name="五年二班").first()
unattachedStudent=[]
while len(class_.students)>0:
    unattachedStudent.append(class_.students.pop()) #与父对象脱离
session.commit #显示地提交事务

上述代码中没有显示地删除任何学生,但由于使用了delete-orphan级联,所以被脱离出班级对象的学生会在session事务提交时会自动从数据库中删除。代码执行后数据库表中的内容的变化:

class表:

class_id name level address
3 五年二班 5 理想路520号3楼

student表:

student_id class_id name age gender address contactor
1 NULL 理想 10 静安区 Null
2 NULL mark 10 静安区 Null
3 NULL 小马哥 9 闸口区 张三
7 NULL 韩永跃 10 静安区 NULL

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/44879.html

相关文章

  • Python-SQLAlchemy3:关系操作

    摘要:本节围绕在中如何定义关系及如何使用关系进行查询进行讲解,使读者能够快速掌握的关系操作。班级与学生为一对多关系,班级与老师之间为多对多关系。三年二班多对多关系的使用通过关联模型实现,在其中分别设置模型和的外键,并且在父模型中设置相应的实现。 上一篇文章:Python-SQLAlchemy:第2节:查询条件设置下一篇文章:Python-SQLAlchemy:第4节:级联 关系数据库是建立...

    William_Sang 评论0 收藏0
  • Python-SQLAlchemy2:查询条件设置

    摘要:上一篇文章第节入门下一篇文章第节关系操作在实际编程中需要根据各种不同的条件查询数据库记录,查询条件被称为过滤器。通配符用百分号表示。以下条语句查询结果相同,都是为的记录。引入或逻辑关键字查询是或者为的记录,返回结果为为的记录 上一篇文章:Python-SQLAlchemy:第1节:SQLAlchemy入门下一篇文章:Python-SQLAlchemy:第3节:关系操作 在实际编程中需...

    selfimpr 评论0 收藏0
  • Python-SQLAlchemy1:SQLAlchemy入门

    摘要:下一篇文章第节查询条件设置是编程语言下的一款开源软件。提供了工具包及对象关系映射工具,使用许可证发行。在关闭连接时会自动进行事务提交操作。引入多条件查询时使用。由于上下文函数退出时会自动提交事务,所以无需显示的调用使新增生效。 下一篇文章:Python-SQLAlchemy:第2节:查询条件设置 SQLAlchemy是Python编程语言下的一款开源软件。提供了SQL工具包及对象关系...

    noONE 评论0 收藏0
  • Python-SQLALchemy

    摘要:因为是工作在一个内部,有时候我们可能不小心做了一些误删除的操作,可以回滚。我们先修改的用户名为,然后重新添加一个新,但是记住这个时候我们还没有。集合类型可以是各种合法类型,比如,但是默认集合是一个。 官方文档 Initialization # 检查是否已经安装以及版本号 >>> import sqlalchemy >>> sqlalchemy.__version__ ’1.1.4‘ ...

    kumfo 评论0 收藏0

发表评论

0条评论

henry14

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<