Oracle 甲骨文-是否有可能;“设置”;更新期间case语句中的值如下?
在更新过程中是否可以在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
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”)。