「转」sqlalchemy 0.9.8 多对多级联删除
转自知乎 http://www.zhihu.com/question/21050551
有 A,B,C,AB,AC五张表
class A(base):
__tablename__ = "a"
id = Column(Integer, primary_key=True)
b = relationship('B', secondary=AB, cascade="delete, delete-orphan", single_parent=True)
c = relationship('C', secondary=AC, cascade="delete, delete-orphan", single_parent=True)
class B(base):
__tablename__ = "b"
id = Column(Integer, primary_key=True)
rules = relationship('A', secondary=AB, cascade="delete, delete-orphan", single_parent=True, passive_deletes=True)
class C(base):
__tablename__ = "c"
id = Column(Integer, primary_key=True)
rules = relationship('A', secondary=AC, cascade="delete, delete-orphan", single_parent=True, passive_deletes=True)
AB = Table(
"AB", Base.metadata,
Column("A_id", Integer, ForeignKey("A.id")),
Column("B_id", Integer, ForeignKey("B.id"))
)
AC = Table(
"AC", Base.metadata,
Column("A_id", Integer, ForeignKey("A.id")),
Column("C_id", Integer, ForeignKey("C.id"))
)
关系是:
A表对B表多对多,关系存放在AB表
A表对C表多对多,关系存放在AC表
操作:
删除A表的数据时,同时删除B,C,AB,AC表与A相关联的数据。
secondary:多对多关联类
cascade:设置级联关系,删除用delete, delete-orphan
single_parent:让级联支持多对多,设置为True
没有此属性会报异常:On X.x, delete-orphan cascade is not supported on a many-to-many or many-to-one relationship when single_parent is not set. Set single_parent=True on the relationship().
passive_deletes: 支持关联(被动)删除,设置为True
没有此属性会报异常:DELETE statement on table 'B' expected to delete 1 row(s); Only 0 were matched.
好了,这样就可以级联删除B,C,AB,AC表与A相关联的数据。
另外一个例子
来自 http://stackoverflow.com/questions/5033547/sqlachemy-cascade-delete
class Parent(Base):
__tablename__ = "parents"
id = Column(Integer, primary_key=True)
child = relationship(Child, backref="parent", passive_deletes=True)
class Child(Base):
__tablename__ = "children"
id = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey("parents.id", ondelete='CASCADE'))
http://www.cnblogs.com/coder2012/p/4746941.html
外键以及relationship例子
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String(32))
addresses = relationship("Address", order_by="Address.id", backref="user")
class Address(Base):
__tablename__ = 'addresses'
id = Column(Integer, primary_key=True)
email_address = Column(String(32), nullable=False)
user_id = Column(Integer, ForeignKey('users.id'))
#user = relationship("User", backref=backref('addresses', order_by=id))
>>> jack = User(name='jack')
>>> jack.addresses
[]
>>> jack.addresses = [Address(email_address='test@test.com'), Address(email_address='test1@test1.com')]
>>> jack.addresses
[<demo.Address object at 0x7f2536564f90>, <demo.Address object at 0x7f2535dc71d0>]
>>> session.add(jack)
>>> session.commit()
mysql> select * from users;
+----+------+
| id | name |
+----+------+
| 1 | jack |
+----+------+
1 row in set (0.00 sec)
mysql> select * from addresses;
+----+-----------------+---------+
| id | email_address | user_id |
+----+-----------------+---------+
| 1 | test@test.com | 1 |
| 2 | test1@test1.com | 1 |
+----+-----------------+---------+
2 rows in set (0.00 sec)
>>> session.query(User.name, Address.email_address).filter(User.id==Address.user_id).filter(Address.email_address=='test@test.com').all()
2015-08-19 14:02:02,877 INFO sqlalchemy.engine.base.Engine SELECT users.name AS users_name, addresses.email_address AS addresses_email_address
FROM users, addresses
WHERE users.id = addresses.user_id AND addresses.email_address = %s
2015-08-19 14:02:02,878 INFO sqlalchemy.engine.base.Engine ('test@test.com',)
[('jack', 'test@test.com')]
http://www.cnblogs.com/whuyt/p/4520850.html
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import uuid
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://demo:demo@127.0.0.1/demo'
app.config['SQLALCHEMY_ECHO'] = True
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
app.config['Debug'] = True
db = SQLAlchemy(app)
# 多对多关系表
teachers_classes = db.Table('teachers_classes',
db.Column('teacher_uuid', db.String(40), db.ForeignKey('teacher.uuid', ondelete='CASCADE', onupdate='CASCADE')),
db.Column('class_uuid', db.String(40), db.ForeignKey('class.uuid', ondelete='CASCADE', onupdate='CASCADE')),
)
# 老师对班级多对多,班级对学生一对多
class Teacher(db.Model):
__tablename__ = 'teacher'
uuid = db.Column(db.String(40), primary_key=True)
name = db.Column(db.String(20), unique=True)
classes = db.relationship('Class', secondary=teachers_classes, backref=db.backref('teachers', lazy='dynamic'), lazy='dynamic', \
cascade='all, delete-orphan', single_parent=True)
class Class(db.Model):
__tablename__ = 'class'
uuid = db.Column(db.String(40), primary_key=True)
name = db.Column(db.String(20), unique=True)
students = db.relationship('Student', backref='class', lazy='dynamic', cascade='all, delete-orphan')
class Student(db.Model):
__tablename__ = 'student'
uuid = db.Column(db.String(40), primary_key=True)
name = db.Column(db.String(20), unique=True)
class_uuid = db.Column(db.String(40), db.ForeignKey('class.uuid', ondelete='CASCADE', onupdate='CASCADE'))
db.drop_all()
db.create_all()
# 建立学生
student_a = [ Student(uuid=str(uuid.uuid1()), name=u'学生'+str(i)) for i in xrange(1, 41)]
student_b = [ Student(uuid=str(uuid.uuid1()), name=u'学生'+str(i)) for i in xrange(41, 81)]
student_c = [ Student(uuid=str(uuid.uuid1()), name=u'学生'+str(i)) for i in xrange(81, 121)]
db.session.add_all(student_a)
db.session.add_all(student_b)
db.session.add_all(student_c)
# 建立班级
class_a = Class(uuid=str(uuid.uuid1()), name=u'班级A', students=student_a)
class_b = Class(uuid=str(uuid.uuid1()), name=u'班级B', students=student_b)
class_c = Class(uuid=str(uuid.uuid1()), name=u'班级C', students=student_c)
db.session.add_all([class_a, class_b, class_c])
db.session.commit()
# 建立老师
teacher_a = Teacher(uuid=str(uuid.uuid1()), name=u'老师A', classes=[class_a, class_b])
db.session.add(teacher_a)
db.session.commit()
teacher_b = Teacher(uuid=str(uuid.uuid1()), name=u'老师B', classes=[class_b, class_c])
db.session.add(teacher_b)
db.session.commit()
teacher_c = Teacher(uuid=str(uuid.uuid1()), name=u'老师C', classes=[class_a, class_b, class_c])
db.session.add(teacher_c)
db.session.commit()
'''
from test import db, Teacher, Class, Student, teachers_classes
1 存在约束关系(sqlalchemy默认有约束的可新增,可更新,但不可删除)
1.1 多对多删除老师
db.session.query(Teacher).filter(Teacher.name==u'老师A').delete() 提示teachers_classes表删除约束
方法
teacher_a = Teacher.query.filter(Teacher.name==u'老师A').first()
classes = Class.query.join(teachers_classes).join(Teacher).filter(Teacher.name==u'老师A').all()
先删除班级关系
for c in classes:
teacher_a.classes.remove(c)
再删除老师
db.session.delete(teacher_a)
查看
teachers_classes、teacher相关记录已删除
1.2 一对多删除班级
db.session.query(Class).filter(Class.name==u'班级C').delete() 提示teachers_classes表删除约束
方法
class_c = Class.query.filter(Class.name==u'班级C').first()
teachers = Teacher.query.join(teachers_classes).join(Class).filter(Class.name==u'班级C').all()
先删除老师关系
for t in teachers:
class_c.teachers.remove(t)
再删除班级
db.session.delete(class_c)
查看
teachers_classes、class相关记录已删除,学生81-120记录的class_uuid更新为null
2 级联删除
cascade默认包括save-update、merge, all关键字包括save-update、merge、refresh-expire、expunge、delete
1.1 多对多删除老师
db.session.query(Teacher).filter(Teacher.name==u'老师A').delete()
查看
teachers_classes、teacher相关记录已删除
1.2 一对多删除班级
db.session.query(Class).filter(Class.name==u'班级C').delete()
查看
teachers_classes、class相关记录已删除,关联的学生81-120记录已删除
1.3 删除学生
db.session.query(Student).filter(Student.class_uuid=='dd5763a8-fff8-11e7-98e2-f0def165d278').delete(synchronize_session='fetch')
查看
学生1-40记录已删除,关联的class数据未删除
'''
「转」sqlalchemy 0.9.8 多对多级联删除的更多相关文章
- Nhibernate 多对多级联删除
在网上找到的方法:查看这里 //-------------------------------------Article.hbm.xml-------------------------------- ...
- React + Node 单页应用「二」OAuth 2.0 授权认证 & GitHub 授权实践
关于项目 项目地址 预览地址 记录最近做的一个 demo,前端使用 React,用 React Router 实现前端路由,Koa 2 搭建 API Server, 最后通过 Nginx 做请求转发. ...
- JavaScript 引擎「V8」发布 8.0 版本,内存占用量大幅下降
上周,JavaScript 引擎「V8」的开发团队在该项目官方网站上正式宣布推出最新的 8.0 版本.这次更新的重点主要集中在错误修复及性能改善上,正式的版本将在数周后随着谷歌 Chrome 80 稳 ...
- 「C++」理解智能指针
维基百科上面对于「智能指针」是这样描述的: 智能指针(英语:Smart pointer)是一种抽象的数据类型.在程序设计中,它通常是经由类型模板(class template)来实做,借由模板(tem ...
- 「2014-3-18」multi-pattern string match using aho-corasick
我是擅(倾)长(向)把一篇文章写成杂文的.毕竟,写博客记录生活点滴,比不得发 paper,要求字斟句酌八股结构到位:风格偏杂文一点,也是没人拒稿的.这么说来,arxiv 就好比是 paper 世界的博 ...
- 使用「max-height」实现自适应高度
.tab-content{ max-height: 0; overflow: hidden; -webkit-transition: max-height .8s; -moz-transition: ...
- 「译」JavaScript 的怪癖 1:隐式类型转换
原文:JavaScript quirk 1: implicit conversion of values 译文:「译」JavaScript 的怪癖 1:隐式类型转换 译者:justjavac 零:提要 ...
- jvm系列(十):如何优化Java GC「译」
本文由CrowHawk翻译,是Java GC调优的经典佳作. 本文翻译自Sangmin Lee发表在Cubrid上的"Become a Java GC Expert"系列文章的第三 ...
- 在Mac中使用「dd」指令烧录ISO镜像文件到U盘
作者:超級efly 發布:2014-07-26 20:22 分類:電腦 閱讀:442 11條評論 大家在Windows系統下可以方便的使用UltraISO程式來燒錄「.ISO」, ...
随机推荐
- JavaScript中创建对象的三种模式
JS中,便于批量创建对象的三种模式: 1.工厂模式:用一个函数封装创建对象的细节,传入必要的参数,在函数内部new一个对象并返回. 缺点:创建的对象无法识别类型(全是Object) 2.构造函数模式: ...
- [CentOS7] vncviewer与windows之间的复制粘贴
转载:https://my.oschina.net/seava/blog/226966 用VNC连接到Linux之后,最纠结的问题就是无法复制粘贴.其实很简单,在Linux里面,打开一个终端,然后输入 ...
- PAT12-012【建最小堆】
卧槽..没看清 值 还有负的.. PS: 注意他说是一个一个插入的,也就是插在完全二叉树的最末位置,然后向上更新. #include<bits/stdc++.h> using namesp ...
- go语言web开发框架_Iris框架讲解(五):MVC包使用
在Iris框架中,封装了mvc包作为对mvc架构的支持,方便开发者遵循mvc的开发原则进行开发. iris框架支持请求数据.模型.持久数据分层处理,并支持各层级模块代码绑定执行. MVC即:model ...
- CF 980D Perfect Groups(数论)
CF 980D Perfect Groups(数论) 一个数组a的子序列划分仅当这样是合法的:每个划分中的任意两个数乘积是完全平方数.定义a的权值为a的最小子序列划分个数.现在给出一个数组b,问权值为 ...
- Mysql-2-数据库基础
(1)mysql是一个小型关系型数据库管理系统. (2)mysql是一个快速.多线程.多用户.健壮的SQL数据库服务器.与其他数据库管理系统比,mysql有以下的优势: mysql是一个关系数据库管理 ...
- docker 推送镜像到私有地址
下面针对的都是docker官网的地址 先登录 docker login 输入docker ID ID不是你的注册邮箱,指的是你登录后显示的ID,然后输入密码 ....此时认为你已经登陆成功了 接着看下 ...
- MarkDown基础语法大全
一.MarkDown是什么? Markdown是一种轻量级的「标记语言」,创始人为约翰·格鲁伯,用简洁的语法代替排版,目前被越来越多的知识工作者.写作爱好者.程序员或研究员广泛使用.其常用的标记符号不 ...
- 008-数据类型(Dictionary)
数据类型(Dictionary) 一.定义 字典是另一种可变容器模型,且可存储任意类型对象. 字典的每个键值 key=>value 对用冒号:分割,每个键值对之间用逗号,分割,整个字典包括在花括 ...
- POJ1036 Gangsters
题目来源:http://poj.org/problem?id=1036 题目大意: 有N个强盗要进入一家饭店打劫,第i个强盗在Ti时刻到达,会抢到Pi的财产.饭店的门有K+1状态,门打开的程度为[0, ...