Oracle Update更新NULL而不是值?

时间:2015-04-02 04:37:04

标签: sql oracle sql-update

我有一个类似

的更新查询
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。 (我知道它不会因为内部查询返回一个数字值。)

如果我对内部查询的值进行硬编码,但是如果我使用绑定参数则会失败。 (但是,当硬编码或使用绑定参数时,都会返回数值。)

我似乎无法知道这个简单查询的错误。

1 个答案:

答案 0 :(得分:1)

  

薪水 - (选择总和(薪水)......

如果salarysub-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>