使用另一行中的字段更新字段

时间:2015-01-28 00:53:01

标签: sql oracle plsql

我有两行:

  • 第1行(LN_DISB_SEQ_NBR = 3)此行包含我需要的字段数据
  • 第2行(最大值(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');

2 个答案:

答案 0 :(得分:0)

好的,我们来看看我的示例代码,抱歉我以前没有时间测试这段代码。但你可以告诉我发生了什么。

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

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的值。

答案 1 :(得分:0)

在许多DBMS中,您只需使用(self)连接编写查询,然后以最少的努力将其转换为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子句将包含查询的连接条件。 where语句的update子句主要由exists要求和(可能相关的)子查询组成,该子查询提供与要更新的行匹配的键值列表。这将与您现有的where语句的update子句紧密匹配。 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列表中。