如何在oracle中将两个更新查询合并为单个更新查询?

问题描述 投票:1回答:2

Table1具有id和ref_id作为复合主键以下给定的查询更新100列

Update table1 
set contri_status = 0 
where status = 1 
  and acc_dr_status = 1 
  and contri_status = 1 
  and id = '111';

下面给出了查询更新3列

Update table1 
set acc_dr_status = 50 
where  status = 1 
  and acc_dr_status = 1 
  and contri_status = 0 
  and id = '111' 
  and ref_id in ('1','2','3');

我希望单个查询执行上面的任务,因此在给定查询下尝试

Update table1 
set  contri_status = 0
   , acc_dr_status = 50    
where status = 1 
  and acc_dr_status = 1 
  and contri_status = 1 
  and id = '111' 
  and ref_id in ('1','2','3');

第二个更新的查询列contri_status取决于第一次查询更新。首先修改的行是唯一一个将被第二个查询修改的行(首先是100个被修改然后是第二个它将变为10行,因为我使用额外的地方ref_id在(...)子句中)。要更新的单个查询应满足两个主要更新日期查询的where子句条件

没有得到正确的结果。

oracle oracle11g oracle-sqldeveloper
2个回答
0
投票

我已经使用case语句进行更新,希望这会有效。

<i>UPDATE TABLE1 SET CONTRI_STATUS = (CASE WHEN CONTRI_STATUS = 1 THEN 0 ELSE CONTRI_STATUS END), 
                     ACC_DR_STATUS = (CASE WHEN CONTRI_STATUS = 0 AND REF_ID IN ('1','2','3') THEN 50 ELSE ACC_DR_STATUS END)
WHERE STATUS = 1 AND ACC_DR_STATUS = 1 AND ID = 111</i>

1
投票

注意:根据OP提供的其他详细信息(在注释中 - 见下文;也添加到问题中),2x更新以串行方式运行,更新#2仅影响受更新#1影响的行的子集。

update table1

set    contri_status = 0,

                    /* case statement limits acc_dr_status update to rows
                       limited by update #2
                    */

       acc_dr_status = case when ref_id in ('1','2','3') 
                            then 50 
                            else acc_dr_status      /* (re)set to its current value */
                       end

/* where clause finds all rows desired by update #1 */

where  status        = 1
and    acc_dr_status = 1
and    contri_status = 1
and    id            = '111'

(重新)将contri_statusacc_dr_status列设置为其当前值的潜在缺点:

  • 额外写入日志
  • 额外的复制开销(如果复制)
  • 不需要的/不需要的触发器活动(可能需要重新编码触发器以解决这些情况)

注意:第一个答案基于原始问题和(我)假设两个更新之间没有依赖关系。

一般来说,您可以:

  • 结合where条款
  • 使用case语句,基于单独的where条件,有条件地设置列

一个可能的update声明使用上述:

update table1
                    /* case statement 'when' clauses should match
                       the corresponding (distinct) where clauses 
                    */

set    contri_status = case when contri_status = 1 
                            then 0 
                            else contri_status      /* (re)set to its current value */
                       end,

       acc_dr_status = case when contri_status = 0 and ref_id in ('1','2','3') 
                            then 50 
                            else acc_dr_status      /* (re)set to its current value */
                       end

/* common where clauses */

where  status        = 1
and    acc_dr_status = 1
and    id            = '111'

/* distinct where clauses */

and    (    contri_status = 1
        or (contri_status = 0 and ref_id in ('1','2','3'))
       )

相同的潜在缺点适用于:(重新)设置具有相同值的contri_statusacc_dr_status列。

© www.soinside.com 2019 - 2024. All rights reserved.