Oracle:在游标声明中使用自定义函数
Posted
技术标签:
【中文标题】Oracle:在游标声明中使用自定义函数【英文标题】:Oracle: Use of a custom function inside a cursor declaration 【发布时间】:2021-03-20 00:13:12 【问题描述】:在一个过程中,我声明了一个游标。在游标声明中,我使用了datum_naar_dagdeel
函数。该函数本身确定星期几加上一天中的部分时间,并将其转换为整数。见代码摘要:
...
CURSOR c_teamvoorkeuren
IS
SELECT DISTINCT
a.seq_afpraak
, a.datum_start
, t.code
, ks.code
, ks.naam
FROM afspraak a
, team t
, kamer_selectie ks
WHERE a.seq_aga_afspraak = p_seq_aga_afspraak
AND t.seq_team = a.seq_team
AND ks.seq_team = a.seq_team
AND ks.dagdeel = instancename.datum_naar_dagdeel(a.datum_start)
...
到目前为止我发现了什么:
功能上的GRANT EXECUTE
已经给public
了。
过程中其他地方使用的其他自定义函数运行良好。
内部带有函数的 select 语句可以完美地独立运行。运行选择部分时,我得到了预期的结果。
当我用1
替换instancename.datum_naar_dagdeel(a.date_start)
时,稍后执行的for 循环运行良好。 1
是给定约会的函数的结果,我正在测试该过程。
但是,当我使用函数而不是1
时,for 循环不会执行单次迭代。因此我得出结论,导致问题的原因是游标内的函数组合。
在游标声明中使用自定义函数时,我是否正在尝试做不可能的事情?是自定义函数还是系统函数有区别吗?
另外,我怀疑我可以构建一个使用 for 循环本身内部函数的检查。并且当检查失败时,使用continue
语句进入下一个迭代步骤。但是,这种解决方案感觉并不干净。
【问题讨论】:
没有异常处理程序……至少现在还没有。我一定会尝试你的建议。所以我猜你怀疑它应该能够工作。正如我通常在 C#.Net 或 SQL Server 上编程一样,我可能需要尝试几次才能使其正常工作。考虑到欧洲的时间,可能要等到周日或周一。 一般来说光标应该可以工作。可以提供函数datum_naar_dagdeel
的代码
这似乎很容易通过调试器逐步清除。大概该函数没有返回预期值。
【参考方案1】:
我试图复制你的解释;似乎没问题在这个例子中。
创建一个函数(我返回一个常量),连接为mike
;将execute
授予public
:
SQL> connect mike/lion
Connected.
SQL> create or replace function f_test
2 return number
3 is
4 begin
5 return 20;
6 end;
7 /
Function created.
SQL> grant execute on f_test to public;
Grant succeeded.
用户scott
将在光标的where
子句(第6 行)中使用该函数:
SQL> connect scott/tiger
Connected.
SQL> create or replace procedure p_test
2 is
3 cursor c1 is
4 select deptno, ename
5 from emp
6 where deptno = mike.f_test;
7 begin
8 for c1r in c1 loop
9 dbms_output.put_line(c1r.deptno ||' '|| c1r.ename);
10 end loop;
11 end;
12 /
Procedure created.
SQL> set serveroutput on
SQL> exec p_test;
20 SMITH
20 JONES
20 SCOTT
20 ADAMS
PL/SQL procedure successfully completed.
SQL>
所以 - 是的,它有效。
如果函数返回,例如null
,没有输出(当然没有):
SQL> create or replace function f_test
2 return number
3 is
4 begin
5 return null;
6 end;
7 /
Function created.
SQL> connect scott/tiger
Connected.
SQL> exec p_test;
PL/SQL procedure successfully completed.
SQL>
您能否分享功能代码以及示例afspraak.datum_start
值?也许我们会注意到一些你没有注意到的东西。
【讨论】:
【参考方案2】:找到了! (……终于)
显然,星期几的编号可能会有所不同,具体取决于会话设置。正如阅读本文的人现在可能已经猜到的那样,我的开发环境与生产环境具有不同的默认设置。我怀疑这与nls_language
设置有关。
因此,代码尝试匹配周日不存在的预订,而不是“让我们与星期一的预订设置匹配”。
只有星期一的测试数据并且不熟悉 Oracle,可能也没有帮助。我确实对今天下午再次开始调试的每个人的反馈感到鼓舞,并感谢您的帮助。
对于那些仍然感兴趣的人,我在下面添加了函数的原始代码。在当前版本中,我更改了工作日编号,从星期一的1
开始。
CREATE OR REPLACE
FUNCTION instancename.datum_naar_dagdeel(datumtijd DATE)
RETURN NUMBER
IS
weekdag NUMBER := 0;
dagdeel NUMBER := 0;
BEGIN
SELECT TO_CHAR(datumtijd, 'D') INTO weekdag FROM dual;
IF (weekdag = 2) THEN dagdeel := dagdeel + 1; END IF; -- Maandagochtend
IF (weekdag = 3) THEN dagdeel := dagdeel + 3; END IF; -- Disndagochtend
IF (weekdag = 4) THEN dagdeel := dagdeel + 5; END IF; -- Woensdagochtend
IF (weekdag = 5) THEN dagdeel := dagdeel + 7; END IF; -- Donderdagochtend
IF (weekdag = 6) THEN dagdeel := dagdeel + 9; END IF; -- Vrijdagochtend
IF (weekdag = 7) THEN dagdeel := dagdeel + 11; END IF; -- Zaterdagochtend
-- Als de afspraak in de middag is, dan +1
IF (TO_NUMBER(TO_CHAR(datumtijd, 'HH24')) >= 12)
THEN dagdeel := dagdeel + 1;
END IF;
RETURN dagdeel;
END;
-- Grants for Function
GRANT EXECUTE ON instancename.datum_naar_dagdeel TO PUBLIC;
GRANT DEBUG ON instancename.datum_naar_dagdeel TO PUBLIC;
注意:我在首次发布后更改了此回复。我的最终发现肯定与最初的问题不符。
【讨论】:
以上是关于Oracle:在游标声明中使用自定义函数的主要内容,如果未能解决你的问题,请参考以下文章