【问题标题】:Opening cursor to fetch and update column values of a table based on other column values of same table in oracle打开游标以根据oracle中同一表的其他列值获取和更新表的列值
【发布时间】:2018-12-04 09:51:27
【问题描述】:

我必须根据以下逻辑更新表中的最后 2 列,该表有 42 列。

  • C42 的字段值(在下面的等式中替换为 N)=(“第一列位置为空/无值” - 1)
  • C41 的字段值 = C(N) 列的字段值,其中 N =(“C42”列的值减去 1)

注意:表值的设置方式是,当在列中遇到第一个空值时;以下其他列在任何特定记录中肯定为空。表有大约 100K 记录,它是一个中间表,上面的计算每周重复一次,新值填充到表中,最后两列再次每周计算。

例如:

C42 = C19   ( 20 - 1) 

C41 = C(20) when 20 columns have some value and 21st column is null

尝试创建存储过程并打开游标以获取计算值,但在创建逻辑和根据逻辑更新每一行时遇到问题。有人可以建议一种有效的方法来执行上述计算逻辑并更新每条记录。提前致谢

【问题讨论】:

  • 不是很清楚。您能否尝试更清楚地解释逻辑,并展示一些具有代表性值的示例(但列数较少 - 可能是一个 MCVE 有 10 列来演示)?我认为您将一个设置为列位置,另一个设置为该列中的值,用于该行中的最后一个非空值...?

标签: oracle plsql sql-update oracle12c database-cursor


【解决方案1】:

如果我理解你在做什么,你就不需要 PL/SQL,你只需要使用 coalesce 和 case 表达式进行简单的更新 - 诚然,两者都有很多术语,所以有点笨拙。

使用一个非常简化的表,只需要担心四列,再加上您要更新的第 41 列和第 42 列:

create table your_table (c1 number, c2 number, c3 number, c4 number, c41 number, c42 number);
insert into your_table (c1, c2) values (11, 12);
insert into your_table (c1, c2, c3) values (23, 24, 25);

您可以通过以相反的顺序合并所有其他列来获得c42 值:

coalesce(c4, c3, c2, c1)

或者在你的情况下:

coalesce(c40, c39, c38, c37, ..., c4, c3, c2, c1)

您可以使用以下 case 表达式获取该列的位置:

case
  when c40 is not null then 40
  when c39 is not null then 39
  ...
  when c4 is not null then 4
  when c3 is not null then 3
  when c2 is not null then 2
  when c1 is not null then 1
end;

您可以通过查询来查看值(使用我的简化表):

select c1, c2, c3, c4,
  coalesce(c4, c3, c2, c1) as c41,
  case
    when c4 is not null then 4
    when c3 is not null then 3
    when c2 is not null then 2
    when c1 is not null then 1
  end as c42
from your_table;

        C1         C2         C3         C4        C41        C42
---------- ---------- ---------- ---------- ---------- ----------
        11         12                               12          2
        23         24         25                    25          3

你可以只更新:

update your_table
set c41 = coalesce(c4, c3, c2, c1),
  c42 =
    case
      when c4 is not null then 4
      when c3 is not null then 3
      when c2 is not null then 2
      when c1 is not null then 1
    end;

2 rows updated.

select * from your_table;

        C1         C2         C3         C4        C41        C42
---------- ---------- ---------- ---------- ---------- ----------
        11         12                               12          2
        23         24         25                    25          3

如果这是您要经常做的事情,那么您可以创建这些虚拟列,这样它们就会自动计算并始终保持最新。

【讨论】:

  • 感谢您的时间和精力。我必须为 C41 找到第二个非空值,但是使用了您的逻辑并为我的解决方案进行了一些调整,它起作用了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-25
  • 1970-01-01
  • 1970-01-01
  • 2021-01-28
  • 2021-10-19
  • 1970-01-01
相关资源
最近更新 更多