【问题标题】:Update fields using fields from another row使用另一行的字段更新字段
【发布时间】:2015-03-26 19:09:13
【问题描述】:

我有 2 行:

  • 第 1 行 (LN_DISB_SEQ_NBR = 3) 此行有我需要的字段数据
  • 第 2 行 (max(LN_DISB_SEQ_NBR) = 6) 此行包含我要更新的字段

我所拥有的示例(不是完整的表格):

LN_DISB_SEQ_NBR | EMPLID  | DNT_CHNG_THS | LN_ACTION_DT | TRNSFR_BATCH | more...
----------------+---------+--------------+--------------+--------------+--------
              3 | 1234567 |          abc |  13-JAN-2015 | TB3399999203 |
              6 | 1234567 |          xyz |  14-JAN-2015 | TB4820000000 | 

我希望更新的示例:

LN_DISB_SEQ_NBR | EMPLID  | DNT_CHNG_THS | LN_ACTION_DT | TRNSFR_BATCH | more...
----------------+---------+--------------+--------------+--------------+--------
              3 | 1234567 |          abc |  13-JAN-2015 | TB3399999203 |
              6 | 1234567 |          xyz |  13-JAN-2015 | TB3399999203 | 

这是我看到的问题:现在,我的 SQL 工作正常,但我对它的构造方式不满意。如果我想添加更多字段进行更改,它的大小将继续增长,并且越来越难以维护(必须更改许多字段)。

我怎样才能重写/压缩它,让它执行相同的任务,但更高效、更干净?

update PS_AG_LOAN_DISB_ACTN3 t1
   set t1.LN_ACTION_STATUS = 'B',
       t1.LN_ACTION_DT = (select LN_ACTION_DT
                            from PS_AG_LOAN_DISB_ACTN3
                           where EMPLID = '1234567'
                             and ITEM_TYPE = '913000300110'
                             and LN_DISB_SEQ_NBR = 3),
       t1.TRNSFR_BATCH = (select TRNSFR_BATCH
                            from PS_AG_LOAN_DISB_ACTN3
                           where EMPLID = '1234567'
                             and ITEM_TYPE = '913000300110'
                             and LN_DISB_SEQ_NBR = 3                    
 where t1.EMPLID = '1234567'
   and t1.LN_DISB_SEQ_NBR = (select max(LN_DISB_SEQ_NBR)
                               from PS_AG_LOAN_DISB_ACTN3
                              where EMPLID = '1234567'
                                and ITEM_TYPE = '913000300110'
                                and LN_ACTION_STATUS = 'R');

【问题讨论】:

  • 您打算将哪个字段更新到其他字段?并取决于什么领域? emplid 不会像您上面的表格那样显示。
  • @EkoJunaidiSalam 我现在期待更新LN_ACTION_DTTRNSFR_BATCH。但未来计划添加更多字段。
  • 看来你要使用merge
  • 不,我想如果你使用流水线函数来更新它会更有效,对吧?

标签: sql oracle plsql


【解决方案1】:

在许多 DBMS 中,您只需编写一个带有 (self)join 的查询,然后用最少的努力将其转换为 update 语句。但 Oracle 不允许在更新语句中加入。

所以我们作弊。

首先,将查询编写为连接。如果不出意外,我们可以看到我们想要更改的行与包含要更改的数据的相应行匹配。

select  *
from    LoanActions la1
join    LoanActions la2
    on  la2.Emp_ID = 1234567
    and la2.Seq_No = 3
where   la1.Emp_ID = 1234567
    and la1.Seq_No =(
        select  Max( Seq_No )
        from    LoanActions
        where   Emp_ID = 1234567
            and Action_Status = 'R');

la1 包含要更改的数据,la2 包含要更改的数据。现在只需以 Oracle 允许的形式编写 update。在set 子句中,列出要更改的字段和提供新数据的子查询。这将是上面的 la2 并且子查询的 where 子句将包含查询的连接条件。 update 语句的 where 子句主要由 exists 要求和(可能相关的)子查询组成,该子查询提供键值列表以匹配您要更新的行。这将与现有 update 语句的 where 子句非常匹配。 Oracle 要求这些是键值。

那么完成的语句是:

update  LoanActions la1
    set la1.Action_Status = 'B',
        (la1.Action_Date, la1.Xfer_Batch )=(
        select  la2.Action_Date, la2.Xfer_Batch
        from    LoanActions  la2
        where   la2.Emp_ID = 1234567
            and la2.Seq_no = 3 )
where   exists(
        select  Max( Seq_No )
        from    LoanActions
        where   Emp_ID = 1234567
            and Action_Status = 'R'
            and Emp_ID = 1234567 );

请注意,这是基于您提供的少量数据。您的 update 语句指的是您从示例数据中省略的字段,因此我必须弥补一些东西。 (并且我从对象名称中删减了一点。)因此该语句很可能需要在您的环境中进行一些细微的调整。但这给了你一个起点。

还要注意,要添加要修改的列,只需将它们添加到 set 列表中即可。

【讨论】:

    【解决方案2】:

    好的,让我们看一下我的示例代码,抱歉我之前没有时间测试此代码。但是你可以告诉我发生了什么事。

    首先,您为表创建一个类型,然后创建一个函数来更新您想要的数据。

    CREATE TYPE testobj AS OBJECT
    {
        LN_DISB_SEQ_NBR NUMBER,
        LN_ACTION_DT DATA,
        TRNSFR_BATCH  VARCHAR2(100)
    };
    
    CREATE OR REPLACE FUNCTION TESTUP(a number, b date, c varchar2)
    RETURN testobj IS
    BEGIN
        RETURN NEW testobj(
            LN_DISB_SEQ_NBR => a,
            LN_ACTION_DT => b,
            TRNSFR_BATCH => c
        );
    END;
    
    UPDATE (SELECT tbl.*, TESTUP(LN_DISB_SEQ_NBR,LN_ACTION_DT,TRNSFR_BATCH) fun_ret FROM PS_AG_LOAN_DISB_ACTN3 tbl) new_value
    SET 
        new_value.LN_ACTION_DT = new_value.fun_ret.LN_ACTION_DT,
        new_value.TRNSFR_BATCH = new_value.fun_ret.TRNSFR_BATCH
    WHERE MAX(LN_DISB_SEQ_NBR) == 6
    

    更新函数的数据供应是您的数据 LN_DISB_SEQ_NBR = 3,该函数将处理它以产生您的 LN_DISB_SEQ_NBR = 6 的值。

    【讨论】:

      猜你喜欢
      • 2011-04-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多