如何将列值从存储过程中的另一个表更新到表中?
Posted
技术标签:
【中文标题】如何将列值从存储过程中的另一个表更新到表中?【英文标题】:How to update column value to a table from another table in a stored procedure? 【发布时间】:2019-09-29 00:05:33 【问题描述】:我创建了一个程序,通过查询包括事务 tbl 在内的其他表来结算所有事务记录,并自动标记参考号和日期。
我尝试做的是我的settle_transaction
过程需要从所选语句生成我的查询并将它们插入到结算表中。同时,我还需要update
ref_num 和处理日期作为事务表的“标记”,这样我在再次调用过程时就不会重复结算。否则,我不知道如何停止显示相同的结算数据两次
这里是输出一个结算tbl的过程和类似下面的结构:
BEGIN
for r_client in
(
select clientid,
client_name, sum(transaction) total_amount
from transaction_tbl tran join terminal_tbl term
on tran.terminalid = term.terminalid join client_tbl c on c.clientid = term.clientid
where refnr is null
)
loop
v_refnr := get_refnr;
insert into settlement_tbl
(
Ref_Num,
Total,
CLIENTID,
TITLE,
processeddate
)
values (v_refnr, total_amount, clientid,
name,sysdate);
update_refnr(v_refnr, sysdate)
end loop;
END
输出:
| reference_num | total amount | client id | client name | processed_date |
|---------------|--------------|-----------|-------------|----------------|
当我执行上述过程时,它会填充来自选择查询的所有结果。但是,如果我再次执行,它将重复相同的结果,尤其是总金额。
我正在寻找一种解决方案,将另一个过程/函数放入此结算过程中,以防止此过程中所选查询的重复记录。
我使用ref. no#
和process_date
将现有的参考编号和日期更新为下面显示的事务tbl。
| transaction_num | transaction amount | reference_num | processed_date |
|-----------------|--------------------|---------------|----------------|
这是我在结算过程中尝试的代码,但仍然显示重复记录,无法更新到交易表。
procedure update_refnr(
p_refnr in number,
p_processeddate in date
)
is
begin
UPDATE TRANSACTION t
SET t.refnr = p_refnr
WHERE EXISTS (SELECT p_processeddate
FROM terminal_tbl
WHERE t.TERMINALID= term.TERMINALID
AND t.processeddate = p_processeddate
AND t.refnr IS NULL);
--exception handling below
end update_refnr;
我也尝试了其他 SQL reference 但无法编译。
理想情况下,当我从存储过程中检索每条记录时,我的结算 tbl 中没有重复记录。
【问题讨论】:
我不确定我是否完全理解您的问题,为什么不修复原始程序,以免产生重复?您在示例和代码中使用了不同的列名或别名,因此很难遵循。也许在问题中添加一些示例数据 因为交易一直在运行,所以我做一个结算表,随时从每个客户端生成一个总金额,否则,它会再次执行之前的交易。希望你能理解我的问题。 不确定,第一个过程是否只是一个选择查询? 看起来您正在该过程中执行 INSERT 而不仅仅是 SELECT。 您是否尝试过使用Merge
。你的问题陈述在我看来更像Merge
。
【参考方案1】:
您只想在新数据不存在时将其插入到您的表中。正如其他人所说,您可以使用 MERGE 来做到这一点:
BEGIN
for r_client in (select clientid,
client_name,
sum(transaction) total_amount
from transaction_tbl tran
join terminal_tbl term
on tran.terminalid = term.terminalid
join client_tbl c
on c.clientid = term.clientid
where refnr is null)
loop
v_refnr := get_refnr;
MERGE INTO settlement_tbl s
USING (SELECT v_refnr AS REF_NUM,
total_amount AS TOTAL,
clientid AS CLIENTID,
name AS TITLE,
SYSDATE AS PROCESSEDDATE
FROM DUAL) d
ON (s.REF_NUM = d.REF_NUM)
WHEN NOT MATCHED THEN
INSERT (Ref_Num, Total, CLIENTID, TITLE, processeddate)
VALUES (d.REF_NUM, d.TOTAL, d.CLIENTID, d.TITLE, d.PROCESSEDDATE);
update_refnr(v_refnr, sysdate);
END LOOP;
END;
WHEN NOT MATCHED
在您的表中不存在v_refnr
时插入新数据。
祝你好运。
【讨论】:
我不仅要向结算表插入新数据,还要将 ref_num 和处理日期链接回我最初从每笔交易中生成总金额的交易表,这样我就可以看到哪个交易已经结算,避免与该 ref_num 重复。 我得到了这个Error(22,17): PL/SQL: ORA-00904: "name": invalid identifier
的客户名称
在您使用的原始代码中 name
- 我只是从那里复制了它。你的意思是client_name
吗?
是的,我听从了你的建议并得到了上述错误,是那个别名导致了这个问题吗?
我想知道为什么在这种情况下使用 dual 而不是 r_client 记录?以上是关于如何将列值从存储过程中的另一个表更新到表中?的主要内容,如果未能解决你的问题,请参考以下文章