在Oracle中一次对补充数据执行两次UPDATE

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Oracle中一次对补充数据执行两次UPDATE相关的知识,希望对你有一定的参考价值。

我有下表需要更新:

USER:

| ID | ACTIVE | REF_COL | COL_2 | COL_3 |
|----|--------|---------|-------|-------|
| 1  |    1   |  value  | value | value |
| 2  |    0   |  value  | value | value |
| 3  |    1   |  value  | value | value |

我分别执行以下两个UPDATE语句:

  1. 声明-1 UPDATE USER SET ACTIVE = 1 WHERE REF_COL IN ( -- Subquery that generates a list of values )
  2. 声明-2 UPDATE USER SET ACTIVE = 0 WHERE REF_COL NOT IN ( -- Subquery that generates a list of values )

生成值列表的子查询对于两个UPDATE查询都是相同的。

是否有任何方法可以帮助我立即执行查询,例如MERGE

使用MERGE语句的以下查询无效:

MERGE INTO USER U
USING (
    -- Subquery that generates a list of values
) T
ON (U.REF_COL = T.VALUE)
WHEN MATCHED THEN
    UPDATE SET U.ACTIVE = 1
WHEN NOT MATCHED THEN
    UPDATE SET U.ACTIVE = 0

由于WHEN NOT MATCHED THEN条款希望有一个INSERT声明。

答案

这是一个merge版本的例子。您必须在源部分中放置逻辑:

merge into users tgt
using (
  select u.ref_col, nvl2(s.ref_col, 1, 0) active
    from users u 
    left join subquery s on u.ref_col = s.ref_col ) src
on (tgt.ref_col = src.ref_col)
when matched then update set active = src.active;

dbfiddle example

另一答案

CASE中使用SET

UPDATE
    USER U
SET
    U.ACTIVE = (CASE WHEN U.REF_COL IN (<subquery>) THEN 0 ELSE 1 END)

DEMO

另一答案

使用Ponder Stibbons在他的answer中提供的想法,我创建了以下查询;我添加的额外逻辑是仅过滤那些需要更新ACTIVE值的行:

MERGE INTO USER U
USING (
    SELECT
        TGT.ID,
        SRC.ACTIVE
    FROM
        USER TGT
        JOIN (
            SELECT
                U.REF_COL,
                NVL2(T.REF_COL, 1, 0) AS ACTIVE
            FROM
                USER U
                LEFT JOIN (
                    -- Subquery that generates a list of values
                ) T ON T.REF_COL = U.REF_COL            
        ) SRC ON TGT.REF_COL = SRC.REF_COL
    WHERE
        TGT.ACTIVE != SRC.ACTIVE
) F
ON (U.ID = F.ID)
WHEN MATCHED THEN
    UPDATE SET
        U.ACTIVE = F.ACTIVE
另一答案

合并伪代码:

MERGE into <target table>

    USING
        <souce table/view/result of subquery>
    ON
        <match condition>
    WHEN MATCHED THEN
        <update clause>
        <delete clause>
    WHEN NOT MATCHED THEN
        <insert clause>

oracle docs如下所示:merge_insert_clause指定在ON子句的条件为false时插入目标表的列的值。如果执行insert子句,则激活目标表上定义的所有插入触发器。如果省略INSERT关键字后面的列列表,则目标表中的列数必须与VALUES子句中的值数相匹配。你不能使用合并或两个更新一个匹配和其他不匹配。

你必须创建一个程序。

CREATE OR REPLACE PROCEDURE all_updates_in_user
IS
   cursor c1 is<<query that generates a list of values>>
BEGIN

  FOR rec in c1
   LOOP

   UPDATE
    USER
SET
    ACTIVE = 1
WHERE
    REF_COL IN rec.columnname;

   UPDATE
    USER
SET
    ACTIVE = 0
WHERE
    REF_COL  NOT IN rec.columnname;  
 END LOOP;
END;

以上是关于在Oracle中一次对补充数据执行两次UPDATE的主要内容,如果未能解决你的问题,请参考以下文章

如何在Oracle中一次执行多条sql语句

(学)如何在Oracle中一次执行多条sql语句

在 oracle 中一次捕获多个异常

ORACLE大数据表Update处理

oracle的grant语句,一次只能授权一张表的访问权限吗?

hql语句怎么写向Hive中一次插入一条数据或一个字段的值,类似关系型数据库的sql语句?