Oracle 中的动态更新查询

Posted

技术标签:

【中文标题】Oracle 中的动态更新查询【英文标题】:Dynamic Update Query in Oracle 【发布时间】:2010-02-23 17:33:08 【问题描述】:

我正在尝试为表创建标准 UPDATE 查询。但是,如果满足某些条件,则应在 UPDATE 语句中包含/排除某些列。

例如:

 UPDATE TBL_PROJECT SET
     REVISION_COUNT = V_REVISION_COUNT
    ,PRIMARY_BRANCH = IN_PRIMARY_BRANCH
    ,PROJECT_STATUS = IN_PROJECT_STATUS
    ...
  WHERE PROJECT_ID = IO_PROJECT_ID
  AND   REVISION_COUNT = IO_REVISION_COUNT
  RETURNING REVISION_COUNT INTO IO_REVISION_COUNT';

但是,该表有两列供提交者和批准者使用。因此,如果状态设置为已提交或已批准,我希望更新这些列。例如。

IF IN_PROJECT_STATUS = 'SUB'
  UPDATE TBL_PROJECT SET
    SUBMITTED_DATE = SYSDATE
ELSIF IN_PROJECT_STATUS = 'APP'
  UPDATE TBL_PROJECT SET
    APPROVED_DATE = SYSDATE
END;

我还需要返回 REVISION_COUNT 和受影响的行数(rowcount)来检查更新是否成功。

编写此查询的最佳方式是什么?我假设动态查询比使用 if-elsif-else 语句更好,因为整个查询在每个块中几乎重复。

【问题讨论】:

【参考方案1】:

您可以编写一个UPDATE,并使用DECODE(或CASE)仅在in_project_status匹配时更新日期:

...
, submitted_date = DECODE( in_project_status, 'SUB', SYSDATE, submitted_date )
, approved_date  = DECODE( in_project_status, 'APP', SYSDATE, approved_date )
...

这样可以避免重复的UPDATE

【讨论】:

@Matt McCormick:在 10g 上,使用 CASE 而不是 DECODE【参考方案2】:

案例示例:

UPDATE TBL_PROJECT 
  SET REVISION_COUNT = v_revision_count,
      PRIMARY_BRANCH = IN_PRIMARY_BRANCH,
      PROJECT_STATUS = IN_PROJECT_STATUS
      ...
      SUBMITTED_DATE = CASE WHEN IN_PROJECT_STATUS = 'APP' THEN SYSDATE ELSE SUBMITTED_DATE END,
      APPROVED_DATE = CASE WHEN IN_PROJECT_STATUS = 'SUB' THEN SYSDATE ELSE APPROVED_DATE END,
WHERE PROJECT_ID = IO_PROJECT_ID
  AND REVISION_COUNT = IO_REVISION_COUNT
RETURNING REVISION_COUNT INTO IO_REVISION_COUNT

【讨论】:

以上是关于Oracle 中的动态更新查询的主要内容,如果未能解决你的问题,请参考以下文章

动态更改oracle游标中的列

动态sql存储过程更新查询问题?

带有表变量的动态查询以循环遍历所有表以在数据库中更新

Oracle Apex - 如何使用动态操作更新更改操作的值列表?

更新查询的动态列名

构建一些动态查询选择并立即在 Oracle PL/SQL 中显示其输出