SQL更新 所有教师的工资将增长5%
SQL更新 只给那些工资低于70000美元的教师涨工资
update的where子句可以嵌套查询语句
SQL更新 对工资低于平均数的教师涨5%的工资
给工资超过100000美元的教师涨3%的工资,其余教师涨5%
update语句的顺序十分重要
case结构
case语句的格式
case语句可以出现的地方
使用标量子查询
使用标量子查询和case
3.9.3 更新
有些情况下,我们可能希望在不改变整个元组的情况下改变其部分属性的值。为达到这一目的,可以使用update
语句。与使用insert
、 delete
类似,待更新的元组可以用查询语句找到
SQL更新 所有教师的工资将增长5%
假设要进行年度工资增长,所有教师的工资将增长5%。我们写出:1
2update instructor
set salary=salary * 1.05;1
2
3
4mysql> update instructor
set salary=salary * 1.05;
Query OK, 12 rows affected (0.01 sec)
Rows matched: 12 Changed: 12 Warnings: 0
上面的更新语句将在 instructor
关系的每个元组上执行一次。
SQL更新 只给那些工资低于70000美元的教师涨工资
1 | update instructor |
1 | mysql> update instructor |
update的where子句可以嵌套查询语句
总之, update
语句的where
子句可以包含select
语句的where
子句中的任何合法结构(包括嵌套的select
)。
和insert
、 delete
类似, update
语句中嵌套的set
可以引用待更新的关系。同样,SQL
首先检查关系中的所有元组,看它们是否应该被更新,然后才执行更新。
SQL更新 对工资低于平均数的教师涨5%的工资
例如,请求”对工资低于平均数的教师涨5%的工资“可以写为如下形式:1
2
3
4
5
6
7update instructor
set salary=salary*1.05
where salary <(
select avg_salary from(
select avg(salary) as avg_salary from instructor
) as Avgs
);1
2
3
4
5
6
7
8
9mysql> update instructor
set salary=salary*1.05
where salary <(
select avg_salary from(
select avg(salary) as avg_salary from instructor
) as Avgs
);
Query OK, 5 rows affected (0.01 sec)
Rows matched: 5 Changed: 5 Warnings: 1
给工资超过100000美元的教师涨3%的工资,其余教师涨5%
我们可以写两条update
语句:1
2
3
4
5
6update instructor
set salary=salary*1.03
where salary >100000;
update instructor
set salary=salary*1.05
where salary<100000;1
2
3
4
5
6
7
8
9
10
11mysql> update instructor
set salary=salary*1.03
where salary >100000;
update instructor
set salary=salary*1.05
where salary<100000;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 0 Changed: 0 Warnings: 0
Query OK, 12 rows affected (0.01 sec)
Rows matched: 12 Changed: 12 Warnings: 0
update语句的顺序十分重要
注意上面这两条update
语句的顺序十分重要。
假如我们改变这两条语句的顺序,工资略少于100000美元的教师将增长8%的工资。
case结构
SQL
提供case
结构,我们可以利用它在一条update
语句中执行前面的两种更新,避免更新次序引发的问题:1
2
3
4
5update instructor
set salary=case
when salary < 100000 then salary*1.05
else salary*1.03
end;1
2
3
4
5
6
7mysql> update instructor
set salary=case
when salary < 100000 then salary*1.05
else salary*1.03
end;
Query OK, 12 rows affected (0.01 sec)
Rows matched: 12 Changed: 12 Warnings: 0
case语句的格式
case
语句的一般格式如下:1
2
3
4
5
6
7case
when pred_1, then result_1
when pred_2, then result_2
...
when pred_n, then result_n
else result0
end
- 如果第一个满足的是谓词
pred_i
,则返回结果result_i
. - 如果没有一个谓词可以满足,则返回
result0
case语句可以出现的地方
case
语句可以用在任何应该出现值
的地方。
使用标量子查询
标量子查询在SQL
更新语句中也非常有用,它们可以用在set
子句中。
考虑这样一种更新:我们把每个student
元组的tot_cred
属性值设为该生成功学完的课程学分的总和。我们假设如果一个学生在某门课程上的成绩既不是”F
“,也不是空,那么他成功学完了这门课程。
我们需要使用set
子句中的子查询来写出这种更新,如下所示:1
2
3
4
5
6update student S
set tot_cred =(
select sum(credits)
from takes natural join course
where S.ID=takes.ID and takes.grade <> 'F' and takes.grade is not null
);1
2
3
4
5
6
7
8mysql> update student S
set tot_cred =(
select sum(credits)
from takes natural join course
where S.ID=takes.ID and takes.grade <> 'F' and takes.grade is not null
);
Query OK, 13 rows affected (0.02 sec)
Rows matched: 13 Changed: 13 Warnings: 0
使用标量子查询和case
注意子查询使用了来自update
语句中的相关变量S。如果一个学生没有成功学完任何课程,上述更新语句将把其tot_cred
属性值设为空。
如果想把这样的属性值设为0的话,我们可以使用另一条update
语句来把空值替换为0。
不过更好的方案是把上述子查询中的”select sun(credits)
“子句替换为如下使用case
表达式的select
子句:1
2
3
4select case
when sum(credits ) is not null then sum(credits)
else 0
end
也就是改为如下形式:1
2
3
4
5
6
7
8
9update student S
set tot_cred =(
select case
when sum(credits ) is not null then sum(credits)
else 0
end
from takes natural join course
where S.ID=takes.ID and takes.grade <> 'F' and takes.grade is not null
);