我们为什么需要DML语句?
当我们在数据库中通过DDL语句创建了表结构后,只是搭建起了数据的骨架,正在有意义的数据信息还需要另外写入。
而这种写入的操作,就需要通过PL/SQL的DML语句来实现。除了写入外,还有对已有数据的修改及删除操作,都属于DML语句。
DML:Data Manipulation Language,数据操纵语言。
DML的关键词
我们将对表中数据的增、删、改操作归为DML语句,有时候会将"查"也归纳为DML语句,但更多时候我们称查询操作为DQL语句。
DML的增、删、改关键字如下:
关键词 | 作用 |
---|---|
INSERT | 增,向表中插入新数据 |
DELETE | 删,将表中已有数据删除 |
UPDATE | 改,对表中已有数据进行修改 |
INSERT
我们使用INSERT INTO - VALUES语句插入新数据。在关系型数据库中,数据都是一行一行出现的,所以我们做的插入和删除操作,都是针对整行数据的。
一般我们有两种方法来插入记录:1.声明法单行插入 2.子查询法多行插入
1.声明法单行插入
通过声明法单行插入是与应用交互时常用的插入方法,该方法就是将明确声明出的表字段及其对应的值,插入表中,若未声明的表字段则置为默认值。其中默认值可以通过表的default约束来指定。需要注意的是,若该表存在有非空约束的字段,且插入时未声明该字段的值,则无法成功插入。
以一张学生信息表为例,声明法单行插入语法如下:
insert into t_student(s_id,name,age,gender)
values(1,'小虎',20,'male');
这样即可插入一行数据至t_student表中。若该表中还有其他字段,如记录班级的classes字段等,在insert时是可以不进行声明并指定值的,会记为默认值。
也可以不声明每列的字段名,直接指定值,但这样必须对没列都指定值,并且指定顺序得按完全照表的字段顺序。一般实际开发过程中不建议使用该方式,代码会难以维护。但还是写个示例吧:
insert into t_student
values(2,'小猪',18,'male',null);
可以直接指定值为null,为字段赋为空值。
2.子查询法多行插入
通过子查询法,可以一次插入多行数据,但这些数据都是数据库中已有的,更适用于存储过程中适用。若用户通过页面输入的数据,数据库中是没有的,则还是需要单行插入。
子查询法,在很多地方都适用,并不是插入时特有的。
我通过一个表结构与表数据的复制案例来介绍。我们在复制表结构时,可以通过where条件的绝对不成立,来做到只复制结构不复制数据的效果:
create table t_student_copy as select * from t_student where 1 = 2;
复制后的表中,我们可以再通过子循环插入,即将values部分换为select,当然我还是推荐使用声明每个列名,在为每列指定值的方式:
insert into t_student_copy(s_id,name,age,gender,classes)
select s_id,name,age+1,gender,classes
from t_student r
where r.classes = 'A';
通过这样方式,可以将查询的结果集插入到指定的表中。查询方式不限,只要结果集的每列数据类型与声明的一致即可,就是说可以多表联合查询,也可以对查询的结果字段进行操作后再插入。
DELETE
对于不再需要的数据,我们可以通过delete语句来进行删除。
delete语句如果不加where条件限制时,则会删除整张表,这里需要注意的是其与truncate的差异,都是清空数据,但truncate是DDL语句,没有逐行删除的操作轨迹,效率更快。
delete from t_student;
通过添加where条件限制,来删除特定的行:
delete from t_student r where r.gender not in ('male','female');
where条件的写法只要符合语句规则都支持,只要有明确的逻辑,就可以删除特定的某一行或多行。where条件中需要多表联合的话,可以使用exists。
UPDATE
如果我们需要对表中已有的数据进行修改操作,则使用update-set-where来实现:
update 表名
set 字段1 = 值,
字段2 = 值,
....
where 条件
会写where条件,让where条件可以圈出想要的数据,并且语法简洁、高效,是一门技术活。掌握了基础语法后,更重要的是在实际开发中多使用多思考,经历过的实际场景多了,就会活学活用了。
值得一提的是,在set值的时候,可以是指明的值,也可以是通过另一个查询select出来的值,如:
update t_emp r
set r.sal = (select avg(t.sal) from t_emp t where t.emp_id != 1)
where r.emp_id = 1;
这个update的意思是,更新员工编号为1的员工薪资,为其他员工薪资的平均数(avg函数是取平均数)。