oracle,过程,带参数的表

Posted

技术标签:

【中文标题】oracle,过程,带参数的表【英文标题】:oracle, procedure, table with params 【发布时间】:2020-07-01 14:45:49 【问题描述】:

我想在 Oracle PL/SQL 中创建一个允许基于参数分析现金流的过程。

create table cfl_param (
contract_type varchar2(20),
new_cfl_month number,
cfl_percentage number
);

create table cfl_table (
contract_id varchar2(20),
contract_type varchar2(20),
cfl_analyze varchar2(20),
cfl_date date,
cfl_value number
);


insert into cfl_param values
('A', 6, 0.4);

insert into cfl_param values
('A', 9, 0.3);

insert into cfl_table values
('A_1', 'A', 'N', date '2020-07-31', 1000);

cfl_param 包含每个合同类型的参数,例如新现金流日期和新现金流百分比。在我的示例中,contract_type A 有两个日期的新现金流,第一个是 6 个月内(​​cfl_value 的 40%),第二个是 9 个月内(​​cfl_value 的 30%)。

表'cfl_table'有关于现金流的数据,最初每个contract_id在cfl_analyze列中都有值'N'。

对于值为“A”的contract_type,该过程必须插入​​3 个新行:2 个具有新日期和cfl_value 的30% 和40%,另一个具有30% 的值但原来是cfl_date。我想获得类似的东西:

Table with results of the procedure

【问题讨论】:

你真的想要一个过程来做这件事,甚至是PL/SQL——它可以用普通的SQL来完成吗?您将向该程序传递什么参数?当前日期的 30% 也是固定的;如果是这样,那应该是cfl_parms 中的另一个 wo(第 0 个月,百分比 0.3)? 程序只是一个选项,什么更合适? 【参考方案1】:

你真的不需要程序。您可以使用以下查询生成额外的值:

select ct.contract_id, ct.contract_type, 'Y' as cfl_analyze,
  ct.cfl_date, 0.3 * ct.cfl_value as cfl_value
from cfl_table ct
where ct.contract_id = 'A_1'
union all
select ct.contract_id, ct.contract_type, 'Y' as cfl_analyze,
  add_months(ct.cfl_date, cp.new_cfl_month) as cfl_date,
  ct.cfl_value * cp.cfl_percentage as cfl_value
from cfl_table ct
join cfl_param cp on cp.contract_type = ct.contract_type
where ct.contract_id = 'A_1';

CONTRACT_ID          CONTRACT_TYPE        C CFL_DATE    CFL_VALUE
-------------------- -------------------- - ---------- ----------
A_1                  A                    Y 2020-07-31        300
A_1                  A                    Y 2021-01-31        400
A_1                  A                    Y 2021-04-30        300

联合的第一个分支获取原始日期,固定 30% 的值;联合的第二个分支根据参数计算其他日期和值。

然后你可以在插入语句中使用它:

insert into cfl_table (contract_id, contract_type, cfl_analyze, cfl_date, cfl_value)
select ct.contract_id, ct.contract_type, 'Y', ct.cfl_date, 0.3 * ct.cfl_value
from cfl_table ct
where ct.contract_id = 'A_1'
union all
select ct.contract_id, ct.contract_type, 'Y',
  add_months(ct.cfl_date, cp.new_cfl_month),
  ct.cfl_value * cp.cfl_percentage
from cfl_table ct
join cfl_param cp on cp.contract_type = ct.contract_type
where ct.contract_id = 'A_1';

3 rows inserted.

select * from cfl_table;

CONTRACT_ID          CONTRACT_TYPE        CFL_ANALYZE          CFL_DATE    CFL_VALUE
-------------------- -------------------- -------------------- ---------- ----------
A_1                  A                    N                    2020-07-31       1000
A_1                  A                    Y                    2020-07-31        300
A_1                  A                    Y                    2021-01-31        400
A_1                  A                    Y                    2021-04-30        300

db<>fiddle

如果您愿意或需要,当然可以将其包装在一个过程中。

如果你把 30% 作为一个额外的参数添加会更简单一些:

insert into cfl_param values
('A', 0, 0.3);

那么你就不需要联合了:

insert into cfl_table (contract_id, contract_type, cfl_analyze, cfl_date, cfl_value)
select ct.contract_id, ct.contract_type, 'Y',
  add_months(ct.cfl_date, cp.new_cfl_month),
  ct.cfl_value * cp.cfl_percentage
from cfl_table ct
join cfl_param cp on cp.contract_type = ct.contract_type
where ct.contract_id = 'A_1';

db<>fiddle

【讨论】:

【参考方案2】:

我认为您需要使用UNION ALL 来生成额外记录,如下所示:

INSERT INTO CFL_TABLE (CONTRACT_ID, CONTRACT_TYPE, CFL_ANALYZE, CFL_DATE, CFL_VALUE
)
    SELECT CT.CONTRACT_ID,
           CT.CONTRACT_TYPE,
           'Y' AS CFL_ANALYZE,
           ADD_MONTHS(CT.CFL_DATE, CP.NEW_CFL_MONTH) AS CFL_DATE,
           CT.CFL_VALUE * CP.CFL_PERCENTAGE AS CFL_VALUE
      FROM CFL_TABLE   CT
      JOIN CFL_PARAM   CP ON CP.CONTRACT_TYPE = CT.CONTRACT_TYPE
     WHERE CT.CONTRACT_ID = 'A_1'
    UNION ALL
    SELECT CT.CONTRACT_ID,
           CT.CONTRACT_TYPE,
           'Y' AS CFL_ANALYZE,
           CT.CFL_DATE,
           CT.CFL_VALUE * CP.CFL_PERCENTAGE AS CFL_VALUE
      FROM CFL_TABLE CT
      JOIN (
        SELECT CONTRACT_TYPE,
               1 - SUM(CFL_PERCENTAGE) AS CFL_PERCENTAGE
          FROM CFL_PARAM
         GROUP BY CONTRACT_TYPE
    ) CP
    ON CP.CONTRACT_TYPE = CT.CONTRACT_TYPE
     WHERE CT.CONTRACT_ID = 'A_1'

【讨论】:

以上是关于oracle,过程,带参数的表的主要内容,如果未能解决你的问题,请参考以下文章

oracle存储过程输入参数能否为空

如何创建带参数的 Oracle 存储过程?

SQL Server 如何执行 带参数的 存储过程

oracle 中用啥命令执行一个带参数的存储过程

Oracle带输入输出参数的存储过程

oracle 带参数存储过程更新