SQL> select empno,ename,deptno,dname from emp;
EMPNO ENAME DEPTNO DNAME
---------- ---------- ---------- --------------------------------------------------
7369 SMITH 20 noname
7499 ALLEN 30 noname
7521 WARD 30 noname
7566 JONES 20 noname
7654 MARTIN 30 noname
7698 BLAKE 30 noname
7782 CLARK 10 noname
7788 SCOTT 20 noname
7839 KING 10 noname
7844 TURNER 30 noname
7876 ADAMS 20 noname
EMPNO ENAME DEPTNO DNAME
---------- ---------- ---------- --------------------------------------------------
7900 JAMES 30 noname
7902 FORD 20 noname
7934 MILLER 10 noname
1111 YODA noname
已选择15行。
需求:
-----------只更新部门10、20的dname
一般人都会这么写:
UPDATE emp
SET emp.dname =
(SELECT dept.dname
FROM dept
WHERE dept.deptno = emp.deptno
AND dept.deptno IN (10, 20));
SQL> select empno,ename,deptno,dname from emp;
EMPNO ENAME DEPTNO DNAME
---------- ---------- ---------- --------------------------------------------------
7369 SMITH 20 RESEARCH
7499 ALLEN 30
7521 WARD 30
7566 JONES 20 RESEARCH
7654 MARTIN 30
7698 BLAKE 30
7782 CLARK 10 ACCOUNTING
7788 SCOTT 20 RESEARCH
7839 KING 10 ACCOUNTING
7844 TURNER 30
7876 ADAMS 20 RESEARCH
EMPNO ENAME DEPTNO DNAME
---------- ---------- ---------- --------------------------------------------------
7900 JAMES 30
7902 FORD 20 RESEARCH
7934 MILLER 10 ACCOUNTING
1111 YODA
已选择15行。
我只更新10和20为扫描30被更新成空值了呢?
Plan hash value: 2456638059
-----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | 15 | 450 | 2 (0)| 00:00:01 |
| 1 | UPDATE | EMP | | | | |
| 2 | TABLE ACCESS FULL | EMP | 15 | 450 | 2 (0)| 00:00:01 |
|* 3 | FILTER | | | | | |
| 4 | TABLE ACCESS BY INDEX ROWID| DEPT | 1 | 13 | 1 (0)| 00:00:01 |
|* 5 | INDEX UNIQUE SCAN | PK_DEPT | 1 | | 0 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - filter(:B1=10 OR :B2=20)
5 - access("DEPT"."DEPTNO"=:B1)
filter("DEPT"."DEPTNO"=10 OR "DEPT"."DEPTNO"=20)
当主查询给子查询传值的时候:B1
相当于子查询为:
SELECT dept.dname
FROM dept
WHERE dept.deptno = :B1;
AND dept.deptno IN (10, 20)
当传入30部门时,返回为空,所以30部分的数据都被跟新为空了
正确写法:
UPDATE emp
SET emp.dname =
(SELECT dept.dname
FROM dept
WHERE dept.deptno = emp.deptno
AND dept.deptno IN (10, 20))
where emp.deptno in (10, 20)