MySQL删除数据(八)
我看到了那天的夕阳,美得如此骄艳,我便决定,追寻夕阳,拼尽余生。
上一章简单介绍了 MySQL更新数据(七),如果没有看过,请观看上一章
MySQL删除数据,是将符合条件的一行或者多行从数据库中进行删除。 但在实际的业务过程中,通常是不能删除数据的,要保留历史,常常会定义一个标识位,如write_status, 1是正常状态, 2是删除状态。 当插入,修改时,write_status的值是1, 当删除时,会将write_status更新成2,来达到删除的目的。 前台展示时,展示不出来, 但是从数据库中查询时,可以查询到。
仍然用的是 yuejl 数据库 里面的 user 表, 并修改 user表中的内容。
一. 删除命令 delete
delete from 表名 [where 条件];
删除用的是 delete 关键字, 后面一般都要跟条件,如果不跟条件,表示删除数据表里面的所有的内容。
可以简单分为, 删除一条记录 和删除多条记录,和删除有外键的记录三种情况。
二. 删除一条记录
删除一条记录时,通常是用 主键进行指定,这样就可以唯一确定一条记录了,达到只删除一条记录的目的。
二.一 指定主键id删除一条记录
如删除 id=6的 名称叫做 小蝴蝶的数据。
delete from user where id=6;
二.二 删除时指定的id 不存在
如删除 id=7的数据,然而 表user 中并没有这一条记录。
delete from user where id=7;
Query OK, 0 rows affected (0.00 sec)
并不会报错,而是执行成功,只是影响的条数是0行。
这一点,与 update 更新时,不存在记录导致的结果一样(具体可以看上一章节update修改单条记录主键不存在的问题)
所以,在删除之前,我们常常验证一下, 该条记录是否还存在于数据库里面, 如果不存在了,则抛出异常,在前台提示用户 ‘该条数据已经被删除,请刷新后再提交’, 如果存在,则才执行数据库的删除语句。
三. 删除多条记录
删除多条记录时, 老蝴蝶把它分成两种情况, 一种是指定的where 条件,可以筛选出多条, 第二种是 不指定条件,全部删除。
三.一 指定的where 条件 可以筛选多条记录
如 指定 id>3 的数据, 有4和5 两条数据。 除了指定主键外,还可以指定其他的列, 如age=24 的记录, 或者 name=‘老蝴蝶的’,也或者 age 在 18到30岁之间的。
这儿用 name=‘老蝴蝶’ 的进行举例验证。
delete from user where name='老蝴蝶';
删除了两行,还剩下三行数据。
三.二 不指定where 条件,全表删除数据
delete from user;
发现, user 表里面的数据全部被删除了。
四. 删除有外键的记录
用 以前的 表 u和 dept 表进行验证。 dept表是父表, u表是子表。
四.一 删除父表中的没有被引用的数据
如 部门编号是 3的记录, 里面并没有相应的员工与其进行关联。 看是否能直接删除该部门?
delete from dept where id=3;
可以直接被删除。
四.二 删除父表中被引用的数据。
如 部门编号为2的记录, 里面有岳泽霖和精小妹 两个员工。 看是否能直接删除?
delete from dept where id=2;
Cannot delete or update a parent row: a foreign key constraint fails (
yuejl
.u
, CONSTRAINTFK_U_deptId
FOREIGN KEY (deptId
) REFERENCESdept
(id
))
删除错误,提示有外键关联.
有两种解决方案, 一是删除外键关联,断开结构的关系,二是将子表中的deptId 修改成null, 断开数据的关系。
下面,老蝴蝶分别演示这两种情况。
四.二.一 将子表的外键属性更新为null,断开数据关系
还是以 部门编号为2的数据进行演示。 开发部下面有岳泽霖和精小妹,员工编号为 3和5.
1 .将员工3和5的 deptId 更新为 null. 然后查询
update u set deptId=null where id=3 or id=5;
2 . 再重新删除 id=2的部门数据。
delete from dept where id=2;
可以正常的删除了。
四.二.二 删除外键关联,断开结构的关系
这个时候,删除 id=1的部门, 还是会报错的,同样是外键关联的错误。
上面断开数据关系,仅仅是断开了 deptId=2的,并没有断开 deptId=1的,所以删除id=1的,同样会报错。
1 . 断开 外键关联。 外键的名称叫做 FK_U_deptId
alter table u drop foreign key FK_U_deptId;
2 . 重新删除 id=1的部门记录
delete from dept where id=1;
其中,很容易明白, 四.二.一 只是针对的某些数据进行删除外键,四.二.二 是针对父表中的所有数据,从结构上断开的。
四.二.三 删除子表数据
无论 deptId 是有值的,还是无值的,都是可以直接删除的。 外键关联,是在删除父表时起作用, 在插入子表和修改子表时起作用。 所以,删除子表,是可以直接删除的。
delete from u where id=3 or id=4;
四.二.四 删除父表时的引用方式
实际上 SQL 有五种方式:
1 . Restrict
2 . No Action
3 . Cascade
4. Set NULL
5. Set Default
MySQL 不支持 set Default , 故只有四种。
其中, Restrict 是默认的方式, 删除和修改时的默认方式。
Restrict : 会检查约束,如果子表中有数据,则不允许删除或者更新。
No Action: 会检查约束,如果子表中有数据,则不允许删除或者更新,与 Restrict 相同。
Cascade: 级联操作。 如果是删除的话,父表可以删除,同时将子表的中数据也删除。 如果是更新的话,父表可以更新,同时将子表 中的外键属性值数据也更新。 (hibernate 常用级别操作)
set null: 父表可以进行删除和更新,同时将 子表中的外键值设置成 null值。
五. Drop, truncate, delete 的区别
删除数据库表中的记录,有三种方式:
1 .drop table 表名
2 . truncate 表名
3 . delete from 表名
三者的侧重点是不一样的,是有很大区别的。 使用者应该根据不同的情况,使用不同的命令执行。
drop 是删除表, 不但会删除表中的数据,而且连表的结构都会删除。
truncate 只会删除表的数据,不会删除表的结构。 是一次性删除数据,相比较于 delete, 效率较高。 会释放空间,自动增长 auto_increment 也会重新开始。
delete 只会删除表的数据,不会删除表的结构。 删除时,是一行一行的删除,相比较于 truncate, 效率低。 不会释放空间, 自动增长 auto_increment 是不会重新开始的。