【发布时间】:2021-04-14 07:54:42
【问题描述】:
我创建了一个简单的确定性函数,我在游标中使用选择查询来调用它 如下图
CREATE TABLE TEMP
(dt DATE);
INSERT INTO TEMP
SELECT SYSDATE FROM DUAL CONNECT BY LEVEL<=3;
INSERT INTO TEMP
SELECT SYSDATE+1 FROM DUAL CONNECT BY LEVEL<=3;
COMMIT;
--2 distinct values
SELECT DISTINCT dt from TEMP;
包功能
CREATE OR REPLACE PACKAGE dummy_fun
AUTHID CURRENT_USER
IS
FUNCTION get_data(
p_date IN DATE)
RETURN DATE
DETERMINISTIC;
END dummy_fun;
/
CREATE OR REPLACE PACKAGE BODY dummy_fun
IS
FUNCTION get_data(
p_date IN DATE)
RETURN DATE
DETERMINISTIC
IS
BEGIN
DBMS_OUTPUT.PUT_LINE('get_data with input (p_date=>'||p_date||' called)');
RETURN p_date+1;
END get_data;
END dummy_fun;
/
FUNCTION CALL - 期望 get_data 在 2 个不同的日期只被调用两次,而如果我只调用这个 SQL,它只运行两次
DECLARE
CURSOR get_date
IS
SELECT dummy_fun.get_data (
dt) from
TEMP;
rec get_date%ROWTYPE;
v_date date;
BEGIN
OPEN get_date;
LOOP
FETCH get_date INTO rec;
EXIT WHEN get_date%NOTFOUND;
NULL;
END LOOP;
CLOSE get_date;
END;
/
输出
get_data with input (p_date=>14-APR-21 called)
get_data with input (p_date=>14-APR-21 called)
get_data with input (p_date=>14-APR-21 called)
get_data with input (p_date=>14-APR-21 called)
get_data with input (p_date=>24-APR-21 called)
get_data with input (p_date=>24-APR-21 called)
get_data with input (p_date=>24-APR-21 called)
get_data with input (p_date=>24-APR-21 called)
**有以下更改,它在光标中工作**
CHANGE 1 - IF THE FUNCTION IS CALLED IN THE WHERE CLAUSE
CURSOR get_date
IS
SELECT 1 from
TEMP
WHERE trunc(sysdate+1)= trunc(ae9_common_code.dummy_fun.get_data (
dt))
CHANGE 2 - Kind of Scalar subquery
CURSOR get_date
IS
SELECT * FROM (
SELECT ae9_common_code.dummy_fun.get_data (
dt) from
TEMP
WHERE 1=1)
CHANGE 3 - BULK COLLECT
SELECT ae9_common_code.dummy_fun.get_data (
dt) BULK COLLECT INTO v_dates from
TEMP
WHERE 1=1;
##OUTPUT FOR ALL THE ABOVE CHANGES ARE##
get_data with input (p_date=>14-APR-21 called)
get_data with input (p_date=>24-APR-21 called)
【问题讨论】:
-
The documentation 说:如果一个带有 DETERMINISTIC 子句的函数违反了这些语义规则中的任何一个,那么它的调用结果、它的值以及对它的调用者的影响都是 未定义。并且:出现DETERMINISTIC选项时,编译器可能使用该标记来提高函数的执行性能。
-
@astentx:我上面违反了什么语义?
-
这个:DETERMINISTIC 函数可能没有副作用。
-
有趣的是:如果我在没有游标的情况下执行相同的
select语句,每个值只会调用一次。如果我将result_cache添加到定义中,它也会在游标中执行一次。看起来文档中有很多 可能 是造成这种情况的原因:有时优化器决定重用计算,有时不依赖于某些内部算法。
标签: oracle function oracle12c deterministic