我们知道sqlalchemy外键约束有4种,分别为:
1、RESTRICT
2、NO ACTION
3、CASCADE
4、SET NULL
其默认为RESTRICT,也就是当父表数据被删除时,从表会拒绝删除。这一现象仅在数据库命令下有效,在ORM层面将会忽略、无视RESTRICT外键约束。下面我们就举例来演示一下
先创建一个csscade_demo数据库,创建数据库cascade_demo命令如下:
create database cascade_demo
新建一个 test.py文件,其代码如下:
from sqlalchemy import create_engine,Column,Integer,String,ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker,relationship
DIALCT = "mysql"
DRIVER = "pymysql"
USERNAME = "root"
PASSWORD = "admin"
HOST = "127.0.0.1"
PORT = "3306"
DATABASE = "cascade_demo"
DB_URI = "{}+{}://{}:{}@{}:{}/{}?charset=utf8".format(DIALCT,DRIVER,USERNAME,PASSWORD,HOST,PORT,DATABASE)
engine = create_engine(DB_URI)
Base = declarative_base(engine)
session = sessionmaker(engine)()
class User(Base):
__tablename__ = "user"
id = Column(Integer , primary_key=True , autoincrement=True)
name = Column(String(50) , nullable=False)
class Arctire(Base):
__tablename__ = "arctire"
id = Column(Integer , primary_key=True , autoincrement=True)
title = Column(String(50) , nullable=False)
uid = Column(Integer ,ForeignKey("user.id"))
author = relationship("User",backref="arctires")
Base.metadata.drop_all()
Base.metadata.create_all()
运行上述代码,我们就可以看到User模型跟Arctire模型成功映射到数据库中。
因为我们要做删除操作,所以表中必须有数据才行
user=User(name="jack")
arctire=Arctire(title="hello python!",uid=1)
arctire.author = user
session.add(user)
session.commit()
运行上述代码,然后查询下数据是否插入到表中
OK,万事俱备!
接下来我们打开数据库命令行终端,输入删除父表数据命令
由上图可知,运行上述命令,从表会拒绝删除
我们再用代码方式删除父表数据试试
user = session.query(User).first()
session.delete(user)
session.commit()
运行上述代码,结果如下
没有报错,说明父表数据已被成功删除,不信我们查询试试!
我们再查询从表数据试试
由上可知从表数据没有删除,但uid为NULL
看到这里,相信大部分同学有个疑问?什么疑问呢?上面外键约束明明为RESTRICT,为什么这里却可以删除父表数据?有什么办法可以实现像命令行拒绝删除?要想避免这一现象,方法很简单!只需在uid这个字段中将nullable=True设置为False即可。
uid = Column(Integer ,ForeignKey("user.id"),nullable=False)
再运行删除从表代码,结果就报错了!
报错了,说明父表数据被删除,从表会拒绝删除!这样就实现了我们想要的结果。