我有两行:
我拥有的示例(不是完整的表格):
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');
答案 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
列表中。