【问题标题】:Oracle complex update statementOracle 复杂更新语句
【发布时间】:2017-07-27 21:41:14
【问题描述】:

我有一个表格,其中数据如下所示

我的要求是以这样一种方式更新此表,即在一个组内(分组将基于 A 列进行),如果 B 列中有值,则应将相同的值更新到 B 列中的其他行该组中的空值。如果 B 列对该组中的所有记录都有空值,则应生成新序列。我也不能为此使用 pl/SQL 块。我需要编写一个 SQL 查询来执行此操作

我的预期输出如下所示

【问题讨论】:

    标签: oracle11g


    【解决方案1】:

    您将无法在更新语句中直接使用sequence_name.nextval,因为该值会随着每一行而增加,这意味着您最终会在 b 列中为每个 a 值提供不同的值。

    我能想到的最好的方法是首先确保每组全为空的 b 值都有一个值,您可以执行以下操作:

    merge into t1 tgt 
      using (select a, 
                    b, 
                    rid, 
                    row_number() over (partition by a order by b) rn 
             from   (select a, 
                            b, 
                            rowid rid, 
                            max(b) over (partition by a) max_b 
                     from   t1) 
             where  max_b is null) src 
        on (tgt.rowid = src.rid and src.rn = 1) 
    when matched then 
    update set tgt.b = t1_seq.nextval;
    

    这会查找给定 a 的所有 b 值为 null 的行,然后更新其中一个以具有下一个序列值。

    完成此操作后,您可以继续并根据该组的最大 b 值填充空值,如下所示:

    update t1 
    set    b = (select max(b) from t1 t2 where t1.a = t2.a) 
    where  b is null;
    

    请参阅 this LiveSQL script 以了解此方法有效的证据。

    【讨论】:

      【解决方案2】:

      类似这样的:

      update table t1
      set B = (select nvl(max(b),sequence_name.nextval) from table where a=t1.a)
      

      Ps:我无法测试这个。 事实上,我们不能在相关子查询中使用序列...... :( 一种解决方法是使用合并:

      merge into teste t1
      using (select max(b) as m,a from teste group by a) t2
      on (t1.a=t2.a)
      when matched then update set b= nvl(t2.m,seq_teste.nextval);
      

      有一件事:即使没有插入 nextval,它也总是会被消耗掉。如果你不想这样,你可能需要一些 pl/sql 代码。

      【讨论】:

      • 我试过这个,我得到一个错误,如下 02287. 00000 - "sequence number not allowed here"
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-31
      相关资源
      最近更新 更多