用其它表中的值更新
我们对emp新增字段dname,然后把dept.dname更新至emp中:
ALERT TABLE emp ADD dname VARCHAR2(20) DEFAULT noname;
这里要求只更新部门(10ACCOUNTING、20RESEARCH)的数据,其他末更新的部门,应该显示默认值noname。
看看下面语句问题在哪
UPDATE emp
SET dname =
(SELECT dept.dname
FROM dept
WHERE dept.deptno =emp.deptno
AND dept.dname IN ('ACCOUNTING','RESEARCH'));
这个语句会对全表更新,没匹配到的部门,dname均被更新为 NULL值,若是线上环境,这样写是严重的问题。正确的写法要加入过滤条件,如下
UPDATE emp
SET dname =
(SELECT dept.dname
FROM dept
WHERE dept.deptno =emp.deptno
AND dept.dname IN ('ACCOUNTING','RESEARCH'))
WHERE EXISTS(SELECT dept.dname
FROM dept
WHERE dept.deptno =emp.deptno
AND dept.dname IN ('ACCOUNTING','RESEARCH'))
也可以用下面的方法实现要求
UPDATE (SELECT emp.dname,dept.dname AS new_dname
FROM emp
INNER JOIN dept ON dept.deptno =emp.deptno
WHERE dept.dname IN('ACCOUNTING','RESEARCH'))
SET dname = new_dname;
这个语句执行前要在表dept中增加唯一索引或主键
alter table add constrains pk_dept primary key(deptno);
第三种方法用MERGE改写
MERGE INTO emp
USING (SELECT dname,deptno FROM dept
WHERE dept.dname IN('ACCOUNTING','RESEARCH') )dept
ON (dept.deptno=emp.deptno)
WHEN MATCHED THEN
UPDATE SET
emp.dname=dept.dname;
建议使用MERGE INTO方法,它只访问了一次dept.。UPDATE语句访问了两次dept。
选自《Oracle 查询优化改写技巧与案例》 有教无类 落落 著