oracle - 如何在 "pipelined table function"、 view 和显式光标之间进行选择

标签 oracle plsql

我将首先说我认为我已经理解的内容。

使用显式游标是因为我们需要稍后重用查询。
如果使用非显式游标(即 cs in (select .........) ),则每次使用游标时都会重新执行请求。因此使用显式游标以提高效率。

为了分解代码,我们可以使用“流水线表函数”或“ View ”来创建游标。
我想知道为什么我应该使用一种解决方案而不是另一种解决方案。

以下是我对这些解决方案的了解:

不赞成也不反对

我可以使用 select 语句提取 View 或流水线表函数的一部分。

骗局

必须声明“流水线表”使用的记录类型和表类型。这需要时间

亲:
我们可以在流水线表(例如循环)中使用 pl/sql 语句的所有可能性

我说的都是真的吗?
还有其他我应该知道的事情吗?

最佳答案

对于这两种游标类型,数据库在打开时都会执行其中的语句。如果游标保持打开状态,您可以稍后从中获取结果而无需重新运行它。因此,两者在这方面同样有效。
显式游标是您可以控制其整个生命周期的游标:打开、获取和关闭。使用隐式游标,PL/SQL 会为您处理这个问题。
当您想要完全控制提取过程时,您可以使用显式游标。这个 bulk collection with a limit 的主要用例.
如果您想在应用程序的许多地方使用相同的查询,显式游标也很方便。在包级别声明它,您可以在任何其他您喜欢的地方引用它:

create or replace package pkg as 
  cursor common_cursor is 
    select ...
end;
这为查询提供了一个单一的定义,这可以使您的代码更易于维护。这样做的问题是,无论您在哪里使用它,您都需要打开、获取和关闭它。在大多数情况下,这会产生更多的代码,而 yield 却很小。
这给我们带来了观点。您可以将公共(public)查询放在 View 中,而不是声明公共(public)游标:
create or replace view common_query as 
  select ...;
然后,您可以在任何其他 SQL 语句中使用它,就像在常规表中一样。所以你可以加入它,等等。你不能直接使用显式游标来做到这一点。您必须将其包装在 (pipelined) table function 中:
create or replace function pipetf
  return ...
  pipelined 
as
  retvals ...;
begin
  open pkg.common_cursor;
  loop
    fetch pkg.common_cursor
    bulk collect into retvals limit 100;
    
    exit when retvals.count = 0;
      
    for i in 1 .. retvals.count loop
      pipe row ( retvals ( i ) ) ;
    end loop;
  end loop;
  close pkg.common_cursor ;
  return;
end pipetf;
/
这允许您在另一个 SQL 语句(如 View )中使用游标:
select * from pipetf;
在这一点上,流水线表函数似乎比 View 要复杂得多。那么为什么要打扰呢?
好吧,它允许您做 View 不能(轻松)做的事情:
  • 以程序方式生成新行或操作结果集
  • 创建参数化查询

  • 通常,您不能将变量传递给像这样的查询(有一些方法,但它们带有陷阱):
    select c2 from ...
    where  c1 = :var
    group  by c2;
    
    而您可以在显式游标中:
    cursor common_cursor ( var int ) is 
      select c2 from ...
      where  c1 = var
      group  by c2;
    
    因此,您可以在 PTF 中使用它来创建可重用的参数化查询:
    create or replace function pipetf ( var int )
      return ...
      pipelined 
    as
      retvals ...;
    begin
      open pkg.common_cursor ( var );
      loop
        fetch pkg.common_cursor
        bulk collect into retvals limit 100;
        
        exit when retvals.count = 0;
          
        for i in 1 .. retvals.count loop
          pipe row ( retvals ( i ) ) ;
        end loop;
      end loop;
      close pkg.common_cursor ;
      return;
    end pipetf;
    /
    
    所以如果你 需要要使用 PL/SQL 创建新行、操作查询结果或想要可重用的参数化查询,流水线表函数是可行的方法。
    为什么?
    添加了 Oracle 数据库 18c polymorphic table functions ,其中涵盖了许多行生成/结果操作示例。从 19.6 开始,您可以创建 SQL 宏,您可以将其用于 emulate parameterized views .这些功能涵盖了流水线表函数(以及更多)的大多数(全部?)用例。
    如果您只需要一个无需额外处理的可重用查询,我会坚持使用 View 。

    关于oracle - 如何在 "pipelined table function"、 view 和显式光标之间进行选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62372477/

    相关文章:

    java - 如何使用 JDBC 连接连接到 Oracle DB,而无需在我的计算机中打开 Oracle

    oracle select into variable 当 select 什么都不返回时?

    xml - 如何在 pl sql 中将聚合 xml 元素分组到另一个父 xml 标记内

    java - ORA-12505 :TNS listener does not currently know of SID given in connect descriptor

    oracle - 如果值是由触发器生成的,该如何注释Id列?

    oracle - 使用PL/SQL Developer插入时出现问题

    plsql - PL/SQL 中的 AND 条件 IF-THEN-ELSE 语句

    sql - Oracle 存储过程变量命名约定

    plsql - 在 oracle PL/SQL 中更新和插入以及 if else 条件

    sql - 跨数据库链接传递引用类型