如何实现流水线函数_PIPELINED关键字与PIPE ROW应用

夏墨酱_4374

夏墨酱_4374

2026-03-30

635人浏览

原创

PIPE ROW 在 Oracle PL/SQL 中怎么写才不报错

直接说结论:pipe row 只能在定义为 pipelined 的函数里用,且函数返回类型必须是已声明的集合类型(比如 table of number),不能是 ref cursor 或标量。

常见错误现象:调用时抛 ORA-06553: PLS-382: expression is of wrong type,或者 ORA-06553: PLS-306: wrong number or types of arguments —— 大多因为返回类型没对上、忘了加 PIPELINED,或在普通函数里硬塞了 PIPE ROW。

  • 函数头必须显式写 RETURN ... PIPELINED,不能只在 body 里用 PIPE ROW
  • 返回集合类型需提前用 CREATE OR REPLACE TYPE 建好,不能用匿名嵌套表(如 RETURN SYS.ODCIVARCHAR2LIST 是特例,但不推荐依赖)
  • PIPE ROW 每次只能传一个元素,类型必须和集合元素类型完全一致(包括精度、字符集、NULL 性)
  • 函数体内不能有 RETURN(除了最后的 END RETURN),否则会提前退出,后续 PIPE ROW 不执行

示例(安全写法):

CREATE OR REPLACE TYPE num_list AS TABLE OF NUMBER;
CREATE OR REPLACE FUNCTION gen_nums(n IN NUMBER) RETURN num_list PIPELINED IS
BEGIN
  FOR i IN 1..n LOOP
    PIPE ROW(i); -- 类型匹配:num_list 元素是 NUMBER,i 是 NUMBER
  END LOOP;
  RETURN; -- 必须有,但不带值
END;

为什么用 PIPELINED 而不是普通函数返回集合

核心区别在执行模型:PIPELINED 函数是“边算边吐”,调用方(比如 SQL 查询)可以逐行消费结果;普通函数得等全部计算完、构造好整个集合再一次性返回,内存和延迟都高。

典型使用场景:处理大结果集但下游只取前几行(SELECT * FROM TABLE(gen_nums(1000000)) WHERE ROWNUM ),或需要流式 join / filter 的 ETL 场景。

  • 非 pipelined 函数:Oracle 会把整个集合加载进 PGA,100 万行 NUMBER 可能占几十 MB 内存
  • Pipelined 函数:每调一次 PIPE ROW,就向调用方送一行,PGA 压力恒定(常驻约 1–2 行缓冲)
  • 兼容性注意:10g+ 支持,但 9i 不支持;如果函数被物化视图引用,部分版本要求必须 DETERMINISTIC(而 pipelined 函数通常不满足)

TABLE(gen_nums(...)) 在 SQL 里怎么避免 ORA-22905 错误

ORA-22905: cannot access rows from a non-nested table item 是最常卡住人的点 —— 根本原因:你用了 TABLE(),但 Oracle 没法确认这个函数返回的是合法嵌套表类型。

触发条件:函数返回类型是本地声明的类型(比如包里定义的 TYPE t IS TABLE OF ...),或用了未授权的系统类型(如 SYS.ODCIDATELIST)。

  • 必须用 CREATE TYPE 在 schema 级别创建集合类型,不能在包或函数内定义
  • 确保函数签名里写的返回类型和 CREATE TYPE 名字**完全一致**(大小写敏感,除非加双引号)
  • 如果函数属于某个 schema,调用方要带 schema 前缀:SELECT * FROM TABLE(my_schema.gen_nums(10))
  • 权限问题:调用方需对类型有 EXECUTE 权限(GRANT EXECUTE ON num_list TO user_x)

PIPE ROW 性能陷阱:什么情况下反而比普通函数慢

不是所有场景都适合 pipelined。当数据量小、调用频繁、或下游必须全量消费时,函数调用开销(context switch、row-by-row 驱动)可能盖过内存优势。

容易踩的坑:

  • 在循环里反复调用 PIPE ROW 但每次只传 1 行,却没做批量缓冲(比如攒 100 行再 pipe 一次)—— 上下文切换成本远高于数据生成本身
  • 函数里做了重 IO(如每次 PIPE ROW 都查一次表),变成 N+1 查询,比一次性 bulk collect + return 更慢
  • 忘记加 PARALLEL_ENABLE 却在并行查询中使用,导致无法并行化,而普通函数有时反能被优化器自动并行
  • 调试时加了 DBMS_OUTPUT.PUT_LINE,每行都触发一次输出,性能断崖下跌(生产务必关掉)

真正关键的复杂点在于:pipelined 不是银弹,它把控制权从 SQL 引擎移交给了 PL/SQL 过程逻辑。一旦你在里面混入阻塞操作、状态依赖或隐式锁,行为就很难预测 —— 这个边界,比语法难得多。

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

2023.10.12

4583

8

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.27

951

4

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

2024.02.23

1209

5

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

6561

10

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

3323

4

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

2024.04.07

6520

11

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

2024.04.29

8961

6

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

1210

5

sql中删除一列的命令是什么
sql中删除一列的命令是什么

在sql中,使用alter table语句可以删除一列,语法为:alter table table_name drop column column_name。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

1072

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.7万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 134.1万人学习