我有一个类似
的更新查询update employees
set salary = salary - (select sum(salary) from employees where manager_id in (101,102))
where employee_id = 105;
上面的sql工作正常但下面的sql正在更新NULL而不是值。
UPDATE table1 a
SET a.col1 = a.col1 - (SELECT SUM(b.col2)
FROM table2 b
WHERE b.col3 = 'AA'
AND b.col4 = '1234'
AND b.col5 = '123456789'
AND b.col6 = 'O'
AND b.col7 IN ( 1, 2, 3, 4 ))
WHERE a.col3 = 'AA'
AND a.col4 = '2313'
AND a.col5 = '987654321';
有人知道原因吗?
如果工资值中包含一些NULL值,它是否会更新NULL。 (我知道它不会因为内部查询返回一个数字值。)
如果我对内部查询的值进行硬编码,但是如果我使用绑定参数则会失败。 (但是,当硬编码或使用绑定参数时,都会返回数值。)
我似乎无法知道这个简单查询的错误。
答案 0 :(得分:1)
薪水 - (选择总和(薪水)......
如果salary
或sub-query
返回 NULL ,则整个表达式会导致NULL。 因此它会更新并将列值设置为NULL。
为避免这种情况,请在整个表达式上使用 NVL 。
例如,
SQL> CREATE TABLE t AS SELECT 1 A FROM dual;
Table created.
SQL>
SQL> SELECT * FROM t;
A
----------
1
SQL>
SQL> UPDATE t SET A = A - (SELECT NULL FROM dual);
1 row updated.
SQL>
SQL> SELECT * FROM t;
A
----------
SQL>
因此,它更新为NULL值,因为表达式导致 NULL 。我们使用 NVL 来避免在NULL时更新:
SQL> ROLLBACK;
Rollback complete.
SQL> UPDATE t SET A = NVL(A - (SELECT NULL FROM dual), A);
1 row updated.
SQL>
SQL> SELECT * FROM t;
A
----------
1
SQL>
问题解决了!
使其更加详细
上述NVL方法与IF NULL THEN REPLACE_VALUE
类似。
所以,你可以写一个case表达式来看它更详细,它只是扩展NVL表达式:
SQL> SELECT * FROM t;
A
----------
1
SQL> UPDATE t
2 SET A =
3 CASE
4 WHEN (A -
5 (SELECT NULL FROM dual
6 )) IS NULL
7 THEN A
8 ELSE (A -
9 (SELECT NULL FROM dual
10 ))
11 END;
1 row updated.
SQL> SELECT * FROM t;
A
----------
1
SQL>