我整天大部分时间都在研究这个问题,但到目前为止仍找不到正确的答案。我试图找到一种在自定义函数中返回SQL查询结果的方法。我们系统中的所有数据都是交易日期和生效日期,通常需要我们在两个时间点之间比较数据。现在,我使用WITH子句提取两个不同的数据集(“ Before”和“ After”)。问题在于用于创建这些数据集的查询非常长,每个CTE基本上都是同一件事,只是有效日期不同。我想找到一种创建函数的方法,该函数可以将有效/事务日期传递给进行比较,因此我的SQL中没有太多冗余逻辑。这很重要-我具有只读访问权限,无法在数据库中创建任何对象。我读过我可以使用Declare语句解决此问题,但到目前为止还无法正确解决。
这是我现在拥有的一个例子。我已经大大简化了查询,所以这不是一个完整的混乱。
WITH effective_date AS (
SELECT to_date(:EFFDT) AS effdt,
to_date(:REPORT_DATE_BEFORE) AS report_dt_before,
to_date(:REPORT_DATE_AFTER) AS report_dt_after
FROM dual),
election_data_before AS (
SELECT *
FROM effective_date efd
CROSS JOIN elections e
WHERE efd.effdt >= e.start_dt
AND efd.effdt < e.until_dt
AND efd.report_dt_before >= e.tran_start_dt
AND efd.report_dt_before < e.tran_until_dt),
election_data_after AS (
SELECT *
FROM effective_date efd
CROSS JOIN elections e
WHERE efd.effdt >= e.start_dt
AND efd.effdt < e.until_dt
AND efd.report_dt_after >= e.tran_start_dt
AND efd.report_dt_after < e.tran_until_dt)
SELECT ...
FROM election_data_before edb
INNER JOIN election_data_after eda
ON edb.employee_id = eda.employee_id
AND edb.benefit_type = eda.benefit_type
WHERE ...
这看起来还不错,但是就像我说的那样,这非常简化。这就是我想要做的。我知道这是垃圾代码,只是试图说明我所描绘的内容。
FUNCTION elections ( effdt date, report_dt date )
RETURN (
SELECT *
FROM elections e
WHERE effdt >= e.start_dt
AND effdt < e.until_dt
AND report_dt >= e.tran_start_dt
AND report_dt < e.tran_until_dt)
SELECT ...
FROM elections(:EFFDT, :REPORT_DT_BEFORE) edb
ON pp.employee_id = edb.employee_id
INNER JOIN elections(:EFFDT, :REPORT_DT_AFTER) eda
ON pp.employee_id = eda.employee_id
AND edb.benefit_type = eda.benefit_type
WHERE ...
我整天都在阅读有关流水线函数和匿名块的信息,但是还不能将它们放在一起。如果有人可以指出正确的方向,或者让我知道我是否最好只使用两个不同的CTE,我将不胜感激。谢谢!
答案 0 :(得分:0)
要创建和使用管道表功能,必须首先创建一个对象类型。
create or replace type election_type as object
(
col1 varchar2(100),
col2 date,
col3 number -- Here you define the name and datatype of the columns you want
-- to return from the select query.
);
/
create or replace type election_type_tab as table of election_type;
-- You need a collection (nested table) type to return multiple records
-- of the type defined above from your function
现在,使用隐式光标for循环定义函数,以提取行并将行传递给调用方。
CREATE OR REPLACE FUNCTION fn_elections (
effdt DATE,
report_dt DATE
) RETURN election_type_tab
PIPELINED
AS
BEGIN
FOR rec IN (
SELECT * --This should return the same columns as that of election_type
FROM elections e --,some_othertable s
WHERE effdt >= e.start_dt AND
effdt < e.until_dt
AND report_dt >= e.tran_start_dt
AND report_dt < e.tran_until_dt
) LOOP
PIPE ROW ( election_type(rec.col1,rec.col2,rec.col3) );
END LOOP;
return;
END;
/
您可以这样称呼它。
select * from TABLE(fn_elections(sysdate,sysdate+1)); --or some other date argument