避免在select子句中进行硬编码



我有以下查询

SELECT decode(detl_cd,'AAA',trunc(amt * to_number(pct) / 100,2),                                                            
'BBB',trunc(amt * to_number(pct) / 100,2),                                                            
'CCC',(amt-trunc(amt * to_number(pct) / 100,2))
INTO trans_amount
FROM dual;

我从游标中获得值detl_cd,从输入文件中获得值amt。

Select tb1.id, tb2.detl_cd,tb2.pct 
from tb1
join tb2 on tb1.agent_code=tb2.agent_code
where tb1.id='1';

每个id有3个detl cd,每个detl代码有不同的计算。如何避免解码中的硬编码。创建表不是一个选项。

输入文件

ID Amount
1  1000
2  2500
3  350

Id 1&2属于被分配了3个不同的detl cd和不同的百分比(pct(的组。

输出文件

ID Detl_cd Amount
1  AAA1     250
1  BBB1     250
1  CCC1     750
2  AAA3     625
2  BBB3     625
2  CCC3    1875
3           350

每个ID具有3个不同的detl_ cd,但是AAA1和AAA2的计算是相同的;CCC。

创建表不是一个选项。

您需要一个存储一组业务规则而不在代码中指定业务规则的解决方案。但也没有创建一个表来存储这些规则。

这只剩下一个用户定义的函数。

create or replace function calc_amount 
( p_detl_cd in varchar2
,p_amt     in number  
,p_pct     in number    )  
return number
as
begin
case substr(p_detl_cd, 1, 3) 
when 'AAA' then return trunc(p_amt * to_number(p_pct) / 100,2);                                                            
when 'BBB' then return trunc(p_amt * to_number(p_pct) / 100,2);                                                           
when 'CCC' then return (p_amt-trunc(p_amt * to_number(p_pct) / 100,2);
end case;
end calc_amount;

您可以在SQL或PL/SQL中调用此函数。您对表和文件有点模糊,所以我不太清楚数据来自哪里,但在PL/SQL:中可能会是这样的

trans_amount := calc_amount(detl_cd, amt, pct);

我希望避免"AAA"的硬编码,因为这些代码将来可能会更改/替换,我不想返工

或者代码可能会发生变化,计算也会发生变化。没关系。残酷的事实是,你必须在的某个地方对代码及其相关规则进行硬编码。不可能有一个无限灵活、软编码的系统。

桌子是最容易维护的东西,它为您提供了最大的灵活性。但是您需要使用动态SQL或函数来应用计算;我更喜欢函数。最糟糕的解决方案是将代码和计算放在外部配置文件中,与输入文件同时加载。

或者,尝试在"上设置一个值;可以改变">。代码(或计算(更改的可能性有多大?多久一次?计算一下,也许你会发现改变不太可能或非常罕见,最简单的选择是坚持解码,并在出现这种情况时承担返工的风险。

顺便说一句,你确定你指的是trunc()而不是round()吗?

我想你可能想要

WITH DATA AS 
(Select tb1.id , tb2.detl_cd,tb2.pct 
from tb1
join tb2 on tb1.agent_code=tb2.agent_code
where tb1.id='1') 
SELECT decode(detl_cd,'AAA',trunc(amt * to_number(pct) / 
100,2),                                                            
'BBB',trunc(amt * to_number(pct) / 100,2),                                                            
'CCC',(amt-trunc(amt * to_number(pct) / 100,2))
as trans_amount 
FROM Data;

相关内容

  • 没有找到相关文章

最新更新