SQL语法基础之DELETE语句

时间:2021-01-16 07:29:52

            SQL语法基础之DELETE语句

                                   作者:尹正杰

版权声明:原创作品,谢绝转载!否则将追究法律责任。 

一.查看帮助信息

1>.查看DELETE的帮助信息

mysql> ? DELETE
Name: 'DELETE'
Description:
Syntax:
DELETE is a DML statement that removes rows from a table. A DELETE statement can start with a WITH clause to define common table
expressions accessible within the DELETE. See
http://dev.mysql.com/doc/refman/8.0/en/with.html. Single-Table Syntax DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name
[PARTITION (partition_name [, partition_name] ...)]
[WHERE where_condition]
[ORDER BY ...]
[LIMIT row_count] The DELETE statement deletes rows from tbl_name and returns the number
of deleted rows. To check the number of deleted rows, call the
ROW_COUNT() function described in
http://dev.mysql.com/doc/refman/8.0/en/information-functions.html. Main Clauses The conditions in the optional WHERE clause identify which rows to
delete. With no WHERE clause, all rows are deleted. where_condition is an expression that evaluates to true for each row to
be deleted. It is specified as described in
http://dev.mysql.com/doc/refman/8.0/en/select.html. If the ORDER BY clause is specified, the rows are deleted in the order
that is specified. The LIMIT clause places a limit on the number of
rows that can be deleted. These clauses apply to single-table deletes,
but not multi-table deletes. Multiple-Table Syntax DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
tbl_name[.*] [, tbl_name[.*]] ...
FROM table_references
[WHERE where_condition] DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
FROM tbl_name[.*] [, tbl_name[.*]] ...
USING table_references
[WHERE where_condition] Privileges You need the DELETE privilege on a table to delete rows from it. You
need only the SELECT privilege for any columns that are only read, such
as those named in the WHERE clause. Performance When you do not need to know the number of deleted rows, the TRUNCATE
TABLE statement is a faster way to empty a table than a DELETE
statement with no WHERE clause. Unlike DELETE, TRUNCATE TABLE cannot be
used within a transaction or if you have a lock on the table. See [HELP
TRUNCATE TABLE] and [HELP LOCK]. The speed of delete operations may also be affected by factors
discussed in
http://dev.mysql.com/doc/refman/8.0/en/delete-optimization.html. To ensure that a given DELETE statement does not take too much time,
the MySQL-specific LIMIT row_count clause for DELETE specifies the
maximum number of rows to be deleted. If the number of rows to delete
is larger than the limit, repeat the DELETE statement until the number
of affected rows is less than the LIMIT value. Subqueries You cannot delete from a table and select from the same table in a
subquery. Partitioned Tables DELETE supports explicit partition selection using the PARTITION
option, which takes a list of the comma-separated names of one or more
partitions or subpartitions (or both) from which to select rows to be
dropped. Partitions not included in the list are ignored. Given a
partitioned table t with a partition named p0, executing the statement
DELETE FROM t PARTITION (p0) has the same effect on the table as
executing ALTER TABLE t TRUNCATE PARTITION (p0); in both cases, all
rows in partition p0 are dropped. PARTITION can be used along with a WHERE condition, in which case the
condition is tested only on rows in the listed partitions. For example,
DELETE FROM t PARTITION (p0) WHERE c < 5 deletes rows only from
partition p0 for which the condition c < 5 is true; rows in any other
partitions are not checked and thus not affected by the DELETE. The PARTITION option can also be used in multiple-table DELETE
statements. You can use up to one such option per table named in the
FROM option. For more information and examples, see
http://dev.mysql.com/doc/refman/8.0/en/partitioning-selection.html. URL: http://dev.mysql.com/doc/refman/8.0/en/delete.html mysql>

2>.相关关键字说明

  DELETE语句用于删除表中已经存储在的整行数据。查看该语句的帮助信息,如第1步所示。下面是对应的关键字说明

    • Tbl_name关键词代表删除数据的目标表

    • Where子句代表被删除数据的满足条件,如果没有where子句则代
表所有表数据都删除 • Order by子句代表删除数据的顺序 • Limit子句代表被删除数据的行数限制

二.Delete案例

1>.DELETE 单表删除举例

mysql> select * from students;
+-----+-----------+--------+---------+
| sid | sname | gender | dept_id |
+-----+-----------+--------+---------+
| 1 | 尹正杰 | boy | 1 |
| 2 | 耿雨星 | boy | 1 |
| 3 | 鲜惠珊 | girl | 2 |
| 4 | 白羽 | boy | 3 |
| 5 | 肖凤 | girl | 4 |
+-----+-----------+--------+---------+
5 rows in set (0.00 sec) mysql>
mysql> DELETE FROM students;
Query OK, 5 rows affected (0.00 sec) mysql>
mysql> select * from students;
Empty set (0.00 sec) mysql>

删除整张表数据(mysql> DELETE FROM students;)

mysql> select * from students;
+-----+-----------+--------+---------+
| sid | sname | gender | dept_id |
+-----+-----------+--------+---------+
| 1 | 尹正杰 | boy | 1 |
| 2 | 耿雨星 | boy | 1 |
| 3 | 鲜惠珊 | girl | 2 |
| 4 | 白羽 | boy | 3 |
| 5 | 肖凤 | girl | 4 |
+-----+-----------+--------+---------+
5 rows in set (0.00 sec) mysql>
mysql>
mysql> DELETE FROM students WHERE sid = 1 ;
Query OK, 1 row affected (0.00 sec) mysql>
mysql> select * from students;
+-----+-----------+--------+---------+
| sid | sname | gender | dept_id |
+-----+-----------+--------+---------+
| 2 | 耿雨星 | boy | 1 |
| 3 | 鲜惠珊 | girl | 2 |
| 4 | 白羽 | boy | 3 |
| 5 | 肖凤 | girl | 4 |
+-----+-----------+--------+---------+
4 rows in set (0.00 sec) mysql>

使用WHERE语句过滤需要删除掉数据(mysql> DELETE FROM students WHERE sid = 1 ;)

mysql> SELECT * FROM students;
+-----+-----------+--------+---------+
| sid | sname | gender | dept_id |
+-----+-----------+--------+---------+
| 1 | 尹正杰 | boy | 1 |
| 2 | 耿雨星 | boy | 1 |
| 3 | 鲜惠珊 | girl | 2 |
| 4 | 白羽 | boy | 3 |
| 5 | 肖凤 | girl | 4 |
+-----+-----------+--------+---------+
5 rows in set (0.00 sec) mysql>
mysql>
mysql> DELETE FROM students ORDER BY sid;
Query OK, 5 rows affected (0.00 sec) mysql>
mysql> SELECT * FROM students;
Empty set (0.00 sec) mysql>

按照sid的值进行升序删除(mysql> DELETE FROM students ORDER BY sid; )

mysql> SELECT * FROM students;
+-----+-----------+--------+---------+
| sid | sname | gender | dept_id |
+-----+-----------+--------+---------+
| 1 | 尹正杰 | boy | 1 |
| 2 | 耿雨星 | boy | 1 |
| 3 | 鲜惠珊 | girl | 2 |
| 4 | 白羽 | boy | 3 |
| 5 | 肖凤 | girl | 4 |
+-----+-----------+--------+---------+
5 rows in set (0.00 sec) mysql>
mysql> DELETE FROM students ORDER BY sid LIMIT 1 ;
Query OK, 1 row affected (0.00 sec) mysql>
mysql> SELECT * FROM students;
+-----+-----------+--------+---------+
| sid | sname | gender | dept_id |
+-----+-----------+--------+---------+
| 2 | 耿雨星 | boy | 1 |
| 3 | 鲜惠珊 | girl | 2 |
| 4 | 白羽 | boy | 3 |
| 5 | 肖凤 | girl | 4 |
+-----+-----------+--------+---------+
4 rows in set (0.00 sec) mysql>
mysql> DELETE FROM students ORDER BY sid DESC LIMIT 1 ;
Query OK, 1 row affected (0.00 sec) mysql>
mysql> SELECT * FROM students;
+-----+-----------+--------+---------+
| sid | sname | gender | dept_id |
+-----+-----------+--------+---------+
| 2 | 耿雨星 | boy | 1 |
| 3 | 鲜惠珊 | girl | 2 |
| 4 | 白羽 | boy | 3 |
+-----+-----------+--------+---------+
3 rows in set (0.00 sec) mysql>

只删除先找到的一行(mysql> DELETE FROM students ORDER BY sid LIMIT 1 ;)

mysql> SELECT * FROM students;
+-----+-----------+--------+---------+
| sid | sname | gender | dept_id |
+-----+-----------+--------+---------+
| 1 | 尹正杰 | boy | 1 |
| 2 | 耿雨星 | boy | 1 |
| 3 | 鲜惠珊 | girl | 2 |
| 4 | 白羽 | boy | 3 |
| 5 | 肖凤 | girl | 4 |
+-----+-----------+--------+---------+
rows in set (0.00 sec) mysql>
mysql> DELETE FROM students WHERE dept_id = 1 ORDER BY sid DESC LIMIT 1;
Query OK, 1 row affected (0.00 sec) mysql>
mysql> SELECT * FROM students;
+-----+-----------+--------+---------+
| sid | sname | gender | dept_id |
+-----+-----------+--------+---------+
| 1 | 尹正杰 | boy | 1 |
| 3 | 鲜惠珊 | girl | 2 |
| 4 | 白羽 | boy | 3 |
| 5 | 肖凤 | girl | 4 |
+-----+-----------+--------+---------+
rows in set (0.00 sec) mysql>

Delete语句中的order by子句决定了删除数据的顺序,配合limit子 句后在某些情况下也非常有用,比如删除最老的一条记录(mysql> DELETE FROM students WHERE dept_id = 1 ORDER BY sid DESC LIMIT 1;)

2>.DELETE 多表删除语句语法

• 同样,被删除的表不能出现在查询子句的子查询中

• Low_priority关键词表示删除语句需要等待其他链接的读此表操作结束后再执行,只作用在MyISAM, MEMORY, and MERGE存储引擎

• Quick关键词是在使用myisam存储引擎时,删除操作不会合并删除表的索引叶节点,这样会在一定程度上加快删除的速度

• ignore关键词代表会忽略删除过程中的一些错误
mysql> SELECT * FROM Dept;
+----+-----------+
| id | demt_name |
+----+-----------+
| 1 | 运维 |
| 2 | 开发 |
| 3 | 测试 |
| 4 | 产品 |
| 5 | 运营 |
| 6 | 法务 |
+----+-----------+
6 rows in set (0.00 sec) mysql>
mysql>
mysql> SELECT * FROM students;
+-----+-----------+--------+---------+
| sid | sname | gender | dept_id |
+-----+-----------+--------+---------+
| 1 | 尹正杰 | boy | 1 |
| 2 | 耿雨星 | boy | 1 |
| 3 | 鲜惠珊 | girl | 2 |
| 4 | 白羽 | boy | 3 |
| 5 | 肖凤 | girl | 4 |
+-----+-----------+--------+---------+
5 rows in set (0.00 sec) mysql>
mysql> DELETE Dept,students FROM Dept INNER JOIN students WHERE Dept.id =students.sid;
Query OK, 10 rows affected (0.00 sec) mysql>
mysql> SELECT * FROM Dept;
+----+-----------+
| id | demt_name |
+----+-----------+
| 6 | 法务 |
+----+-----------+
1 row in set (0.00 sec) mysql>
mysql> SELECT * FROM students; Empty set (0.00 sec) mysql>

从一个或多个表中删除满足条件的数据,其中的 table_references代表了多个表的join操作(mysql> DELETE Dept,students FROM Dept INNER JOIN students WHERE Dept.id =students.sid;)

mysql> SELECT * FROM students;
+-----+-----------+--------+---------+
| sid | sname | gender | dept_id |
+-----+-----------+--------+---------+
| 1 | 尹正杰 | boy | 1 |
| 2 | 耿雨星 | boy | 1 |
| 3 | 鲜惠珊 | girl | 2 |
| 4 | 白羽 | boy | 3 |
| 5 | 肖凤 | girl | 4 |
+-----+-----------+--------+---------+
5 rows in set (0.00 sec) mysql>
mysql> SELECT * FROM Dept;
+----+-----------+
| id | demt_name |
+----+-----------+
| 1 | 运维 |
| 2 | 开发 |
| 3 | 测试 |
| 4 | 产品 |
| 5 | 运营 |
| 6 | 法务 |
+----+-----------+
6 rows in set (0.00 sec) mysql>
mysql> DELETE FROM students,Dept USING students INNER JOIN Dept WHERE students.sid = Dept.id;
Query OK, 10 rows affected (0.00 sec) mysql>
mysql> SELECT * FROM students; Empty set (0.00 sec) mysql>
mysql> SELECT * FROM Dept; +----+-----------+
| id | demt_name |
+----+-----------+
| 6 | 法务 |
+----+-----------+
1 row in set (0.00 sec) mysql>

除了上面的那种写法外,还可以用这种方式写也能达到相同的效果,如果有多张表继续使用INNER JOIN关键字继续跟上相应的表即可(mysql> DELETE FROM students,Dept USING students INNER JOIN Dept WHERE students.sid = Dept.id;)

3>.DELETE别名使用方式

mysql> select * from teacher;
+------+-------------+------------+
| t_id | course_name | teacher_id |
+------+-------------+------------+
| 7 | Chinese | 6 |
| 8 | English | 7 |
| 9 | Physic | 8 |
+------+-------------+------------+
3 rows in set (0.00 sec) mysql> select * from student;
+--------+--------------+
| stu_id | stu_name |
+--------+--------------+
| 6 | 火影忍者 |
| 7 | 火影忍者 |
| 9 | 沙和尚 |
+--------+--------------+
3 rows in set (0.00 sec) mysql>
mysql> DELETE t1,t2 FROM teacher AS t1 INNER JOIN student AS t2 WHERE t1.t_id =t2.stu_id;
Query OK, 4 rows affected (0.01 sec) mysql>
mysql> select * from student; +--------+--------------+
| stu_id | stu_name |
+--------+--------------+
| 6 | 火影忍者 |
+--------+--------------+
1 row in set (0.00 sec) mysql>
mysql> select * from teacher; +------+-------------+------------+
| t_id | course_name | teacher_id |
+------+-------------+------------+
| 8 | English | 7 |
+------+-------------+------------+
1 row in set (0.00 sec) mysql>
mysql> select * from teacher;
+------+-------------+------------+
| t_id | course_name | teacher_id |
+------+-------------+------------+
| 7 | Chinese | 6 |
| 8 | English | 7 |
| 9 | Physic | 8 |
+------+-------------+------------+
3 rows in set (0.00 sec) mysql>
mysql> select * from student;
+--------+--------------+
| stu_id | stu_name |
+--------+--------------+
| 6 | 火影忍者 |
| 7 | 火影忍者 |
| 9 | 沙和尚 |
+--------+--------------+
3 rows in set (0.00 sec) mysql>
mysql> DELETE FROM t1,t2 USING teacher AS t1 INNER JOIN student AS t2 WHERE t1.t_id = t2.stu_id;
Query OK, 4 rows affected (0.00 sec) mysql>
mysql> select * from student; +--------+--------------+
| stu_id | stu_name |
+--------+--------------+
| 6 | 火影忍者 |
+--------+--------------+
1 row in set (0.00 sec) mysql>
mysql> select * from teacher; +------+-------------+------------+
| t_id | course_name | teacher_id |
+------+-------------+------------+
| 8 | English | 7 |
+------+-------------+------------+
1 row in set (0.00 sec) mysql>

另一种写法(mysql> DELETE FROM t1,t2 USING teacher AS t1 INNER JOIN student AS t2 WHERE t1.t_id = t2.stu_id;)

三.DROP、TRUNCATE和DELETE的区别

1>.drop

  drop是DDL,会隐式提交,所以,不能回滚,不会触发触发器。

  drop语句删除表结构及所有数据,并将表所占用的空间全部释放。

  drop语句将删除表的结构所依赖的约束,触发器,索引,依赖于该表的存储过程/函数将保留,但是变为invalid状态。

  相关笔记请参考:https://www.cnblogs.com/yinzhengjie/p/10331914.html

2>.truncate

  truncate是DDL,会隐式提交,所以,不能回滚,不会触发触发器。

  truncate会删除表中所有记录,并且将重新设置高水线和所有的索引,缺省情况下将空间释放到minextents个extent,除非使用reuse storage,。不会记录日志,所以执行速度很快,但不能通过rollback撤消操作(如果一不小心把一个表truncate掉,也是可以恢复的,只是不能通过rollback来恢复)。

  对于外键(foreignkey )约束引用的表,不能使用 truncate table,而应使用不带 where 子句的 delete 语句。

  truncate table不能用于参与了索引视图的表。  
mysql> SHOW TABLES;
+-----------------------+
| Tables_in_yinzhengjie |
+-----------------------+
| course |
| score_graph |
| student |
| teacher |
| view_teacher |
+-----------------------+
5 rows in set (0.00 sec) mysql>
mysql> SELECT * FROM student;
+----+-----------+------------+
| id | name | teacher_id |
+----+-----------+------------+
| 1 | 尹正杰 | 1 |
| 2 | 尹正杰 | 1 |
+----+-----------+------------+
2 rows in set (0.00 sec) mysql>
mysql> TRUNCATE TABLE student;
Query OK, 0 rows affected (0.01 sec) mysql>
mysql> SELECT * FROM student;
Empty set (0.00 sec) mysql>
mysql>

TAUNCATE案例展示(mysql> TRUNCATE TABLE student;)

3>.delete

  delete是DML,执行delete操作时,每次从表中删除一行,并且同时将该行的的删除操作记录在redo和undo表空间中以便进行回滚(rollback)和重做操作,但要注意表空间要足够大,需要手动提交(commit)操作才能生效,可以通过rollback撤消操作。

  delete可根据条件删除表中满足条件的数据,如果不指定where子句,那么删除表中所有记录。

  delete语句不影响表所占用的extent,高水线(high watermark)保持原位置不变。

  相关笔记请参考: https://www.cnblogs.com/yinzhengjie/p/10275086.html