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

时间:2021-06-30 22:01:25

标签: sql oracle plsql case hardcoded

我有以下查询

 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 的计算是相同的,因此 BBB 和 CCC 也是如此。

2 个答案:

答案 0 :(得分:1)

<块引用>

创建表格不是一种选择。

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

那只留下一个用户定义的函数。

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()

答案 1 :(得分:0)

我猜你可能想要

 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;