WITH子句中的PL/SQL

Posted

技术标签:

【中文标题】WITH子句中的PL/SQL【英文标题】:PL/SQL inside WITH clause 【发布时间】:2017-02-10 15:38:59 【问题描述】:

不行,在WITH子句里不行吗?

WITH start1 AS 
(
  BEGIN
    EXECUTE immediate 'Select 1 from dual';
  END;
)
SELECT * FROM start1

【问题讨论】:

您正试图在一段 SQL 代码中使用 PLSQL 块,而不管 WITH。这行不通。你需要做什么? 您使用的是哪个版本的 Oracle?我相信 12c 可以做到这一点。请参阅此oracle.com/technetwork/database/features/plsql/… 的第 9 页。 看起来您使用的是 Oracle 12,它允许 WITH 子句中的函数和过程。但是你在这里想要做什么还不清楚。 start1 似乎是一个过程(反正语法是错误的); select * from start1 是什么意思?从程序中选择是什么意思?这没有任何意义。 “它不起作用”是什么意思 - 至少告诉我们会发生什么,以及您的预期。除了已经提到的事情之外,您的动态查询无论如何都不会执行,因为它没有选择 into 任何东西。但是你似乎在尝试的东西无论如何都没有意义。 【参考方案1】:

如果您尝试在 WITH 子句中使用允许 PL/SQL 的 Oracle 12c 功能,则说明您没有正确使用它。

请记住,您提交的每个 SQL 语句都必须有一组明确定义的列,它将返回。牢记这一点,您将有两种选择来完成您所追求的目标。

选项 1 -- 在 SELECT 结果中返回一个游标

此选项不要求您知道动态 SQL 语句的行类型,但无论谁/什么消耗您的查询结果,都需要获取和处理游标。像这样:

with function start1 return sys_refcursor is
  l_rc SYS_REFCURSOR;
BEGIN
  OPEN l_rc FOR 'SELECT 1 FROM DUAL';
  RETURN l_rc;
END;
select start1 from dual;

START1           
---------------- 
(Cursor)         

The (cursor) value in the result set is the result set of the dynamic SQL statement (i.e., `SELECT 1 FROM DUAL`).

选项2——提前了解和使用动态SQL的rowtype

此选项要求您为动态 SQL 的行类型创建一个对象类型和一个行类型的表。

CREATE OR REPLACE TYPE rc_rowtype IS OBJECT ( val NUMBER );

CREATE OR REPLACE TYPE rc_tabtype IS TABLE OF rc_rowtype;

with function start1 return rc_tabtype is
  l_results rc_tabtype;
  l_rc SYS_REFCURSOR;
BEGIN
  OPEN l_rc FOR 'SELECT rc_rowtype(1) FROM DUAL';
  FETCH l_rc BULK COLLECT INTO l_results;
  CLOSE l_rc;
  DBMS_OUTPUT.PUT_LINE('l_results.COUNT = ' || l_results.count);
  RETURN l_results;
END;
select * FROM table(start1);

VAL                                          
--- 
  1 

【讨论】:

可以构建返回动态结果集的 SQL 语句,例如我的回答 here。但在实践中,这几乎不是人们想要做的。除非 OP 有一些极端情况,否则他几乎肯定应该使用您的建议之一。

以上是关于WITH子句中的PL/SQL的主要内容,如果未能解决你的问题,请参考以下文章

PL/SQLPL/SQL过程

Oracle——PL/SQL

oracle(sql)基础篇系列——PLSQL游标存储过程触发器

JPQL 中的 HQL 'with' 子句

GREENPLUM中的with,即CTE用法,转自gp中文网文档

我可以在 IN 子句中使用 WITH 子句中的表吗?