Oracle 甲骨文-是否有可能;“设置”;更新期间case语句中的值如下?

Oracle 甲骨文-是否有可能;“设置”;更新期间case语句中的值如下?,oracle,Oracle,在更新过程中是否可以在case语句中“设置”如下所示的值 UPDATE TABLE1 CASE WHEN COL1 = 'A' THEN SET COL2 = 10, COL3 = 20, COL4 = 30 WHEN COL1 IN ('B','N') THEN SET COL2 = 1, COL3 = 5, COL4 = 7 WHEN COL1 = 'D' THEN SET COL2 = 11, COL3 = 13, COL4 = 17 ELSE

在更新过程中是否可以在case语句中“设置”如下所示的值

UPDATE TABLE1
  CASE WHEN COL1 = 'A' THEN SET COL2 = 10, COL3 = 20, COL4 = 30
       WHEN COL1 IN ('B','N') THEN SET COL2 = 1, COL3 = 5, COL4 = 7
       WHEN COL1 = 'D' THEN SET COL2 = 11, COL3 = 13, COL4 = 17
       ELSE SET COL2 = 0, COL3 = 0, COL4 = 0
  END;

相应的有效语法如下所示

UPDATE TABLE1 SET
  COL2 = (CASE WHEN COL1 = 'A' THEN 10
               WHEN COL1 IN ('B','N') THEN 1
               WHEN COL1 = 'D' THEN 11
               ELSE 0
          END), 
  COL3 = (CASE WHEN COL1 = 'A' THEN 20
               WHEN COL1 IN ('B','N') THEN 5
               WHEN COL1 = 'D' THEN 13
               ELSE 0
          END), 
  COL4 = (CASE WHEN COL1 = 'A' THEN 30
               WHEN COL1 IN ('B','N') THEN 7
               WHEN COL1 = 'D' THEN 17
               ELSE 0
          END);

为了通过
case
执行此操作,您必须对每个字段重复
case
(如@MaheswaranRavisankar所示)。这就是
case
的工作方式。另一种方法是创建一个提供相同结果的子查询。虽然时间较长,但它会将相关值分组在一起,这样可能更可读/更易于维护

考虑到需要将所有不匹配的值设置为零,我将首先将所有值设置为零,然后将匹配项更新为适当的值

UPDATE table1
SET    col2 = 0, col3 = 0, col4 = 0;

UPDATE table1
SET    (col2, col3, col4) =
          (SELECT a.col2, a.col3, a.col4
           FROM   (SELECT 'A' AS col1,
                          10 AS col2,
                          20 AS col3,
                          30 AS col4
                   FROM   DUAL
                   UNION ALL
                   SELECT 'B' AS col1,
                          5 AS col2,
                          5 AS col3,
                          7 AS col4
                   FROM   DUAL
                   UNION ALL
                   SELECT 'N' AS col1,
                          5 AS col2,
                          5 AS col3,
                          7 AS col4
                   FROM   DUAL
                   UNION ALL
                   SELECT 'D' AS col1,
                          13 AS col2,
                          7 AS col3,
                          17 AS col4
                   FROM   DUAL) a
           WHERE  a.col1 = table1.col1);

这也暗示了另一个选择:也许你应该考虑创建一个带有这些值的表,而不是将它们嵌入到SQL中。

看起来像是在尝试合并,但有一个例外。除了将所有不匹配行更新为0的逻辑之外,您可以在单个merge语句中更新该表,如下所示

SQL> create table tab1
(
col1 varchar2(10),
col2 number,
col3 number,
col4 number,
merge_flag char(1)
)
Table created.
SQL> insert into tab1 values ('A', 10,11,12,null)
1 row created.
SQL> insert into tab1 values ('B', 20,21,22,null)
1 row created.
SQL> insert into tab1 values ('C', 30,31,32,null)
1 row created.
SQL> commit
Commit complete.
SQL> select * from tab1

COL1             COL2       COL3       COL4 MERGE_FLAG
---------- ---------- ---------- ---------- ----------
A                  10         11         12           
B                  20         21         22           
C                  30         31         32           

3 rows selected.
SQL> merge into tab1 t
using (
    select 'A' as col1, 10 as col2, 20 as col3, 30 as col4 from dual
    union
    select 'B' as col1, 1 as col2, 5 as col3, 7 as col4 from dual
    union
    select 'N' as col1, 1 as col2, 5 as col3, 7 as col4 from dual
    union
    select 'D' as col1, 11 as col2, 13 as col3, 17 as col4 from dual
) x
on (t.col1 = x.col1)
when matched then
    update set t.col2 = x.col2, t.col3 = x.col3, t.col4 = x.col4, t.merge_flag = 'X'
Merge successfully completed.
SQL> commit
Commit complete.
SQL> select * from tab1

COL1             COL2       COL3       COL4 MERGE_FLAG
---------- ---------- ---------- ---------- ----------
A                  10         20         30 X         
B                   1          5          7 X         
C                  30         31         32           

3 rows selected.

可以在合并后运行单个更新,以更改所有与0不匹配的行

谢谢,但我正试图避免使用case语句对每一列进行更新。我尝试了您的方法,但它错误地使用了
SQL错误:ORA-01789:query block的结果列01789的数量不正确。00000-“查询块的结果列数不正确”
当然,您可以将dml语句从
SET(col2,col3,col4)
更改为
SET(col1,col2,col3,col4)
,这将产生所需的结果。总而言之,这是一个可靠的答案。答案已经更新,以解决@Patrick提出的问题。或者,您可以先将每一行设置为全零,然后运行
合并
,这样就不需要
合并标志
列。合并标志列只是为了说明正在更新哪些字段,合并不需要它们。合并不需要它们,但是,为了将未合并的值更新为零,您需要知道合并了哪些行。我以为那就是它的意图。我明白了。您不需要知道合并了哪些行,只需运行一个更新,其中col1不在“merge”列表中(在我的示例中为“x”)。