无法在BEGIN/END块中放置WITH FUNCTION子句

use*_*165 5 plsql with-statement oracle12c

为什么下面的代码没有编译

DECLARE
c number;
BEGIN
WITH
FUNCTION calculate(i IN NUMBER) RETURN NUMBER
AS
r number;
BEGIN
  r := i*i;
  RETURN r;
END;
select calculate(1) INTO c from dual;
END;
Run Code Online (Sandbox Code Playgroud)

给出以下错误:

Error report -
*ORA-06550: line 5, column 10:
PL/SQL: ORA-00905: missing keyword
ORA-06550: line 4, column 1:
PL/SQL: SQL Statement ignored
06550. 00000 -  "line %s, column %s:\n%s"
Cause:    Usually a PL/SQL compilation error.
Action:*
Run Code Online (Sandbox Code Playgroud)

WITH
FUNCTION calculate(i IN NUMBER) RETURN NUMBER
AS
r number;
BEGIN
  r := i*i;
  RETURN r;
END;
select calculate(1) from dual;
Run Code Online (Sandbox Code Playgroud)

编译?

Oracle版本信息

  • Oracle Database 12c企业版12.1.0.2.0版 - 64位生产
  • PL/SQL版本12.1.0.2.0 - 生产

Ale*_*ole 3

PL/SQL 似乎还不支持这种构造。据推测,它将在未来的版本中添加。

与此同时,这令人不愉快,但您可以使用动态 SQL,它继续在可以理解的 SQL 上下文中运行您的工作语句:

DECLARE
  c number;
BEGIN
  EXECUTE IMMEDIATE '
WITH
FUNCTION calculate(i IN NUMBER) RETURN NUMBER
AS
  r number;
BEGIN
  r := i*i;
  RETURN r;
END;
select calculate(2) from dual'
  INTO c;
  DBMS_OUTPUT.PUT_LINE(c);
END;
/

4
Run Code Online (Sandbox Code Playgroud)

的文档select into并未显示withPL/SQL 甚至对于子查询块也支持该子句,但即使在早期版本中也确实有效。因此它也不引用新的 PL/SQL 声明语法。根据在运行 12.2.0.1 的 Oracle Live SQL 平台上进行的实验,12cR2 也不支持它。

  • 似乎与 https://oracle-base.com/articles/12c/with-clause-enhancements-12cr1#plsql-support 中的建议一致 (2认同)