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

时间:2017-12-14 20:48:25

标签: oracle oracle11g oracle-sqldeveloper

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




 更新table1
设置contri_status = 0
 status = 1
和acc_dr_status = 1
和contri_status = 1
和id ='111';
  




以下给出的查询更新3列




 更新table1
设置acc_dr_status = 50
其中status = 1
和acc_dr_status = 1
和contri_status = 0
和id ='111'
和ref_id in('1','2','3');
  




我希望单个查询在上述任务中执行所以尝试下面给出的查询




 更新table1
设置contri_status = 0
 ,acc_dr_status = 50
 where status = 1
和acc_dr_status = 1
和contri_status = 1
和id ='111'
和ref_id in('1','2','3');
  




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





未获得正确的结果。




2 个答案:

答案 0 :(得分: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列。

答案 1 :(得分: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>