暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle中的管道函数(pipeline)迁移到磐维分布式

原创 有教无类 2025-05-07
139

适用范围

Oracle迁移到磐维分布式

问题概述
迁移一个项目时发现客户的系统中大量的使用了管道函数(pipeline),磐维分布式目前暂时不支持pipeline。如果迁移为表函数,使用时并不支持函数table(),改动较大。但是磐维分布式支持unnest函数,只要返回数据集即可。因此可以把oracle中的管道函数进行改造,改为返回数据集。

Oracle中源码示例

CREATE OR REPLACE TYPE type_emp_row AS OBJECT ( empno NUMBER(4), ename VARCHAR2(10), job VARCHAR2(9), mgr NUMBER(4), hiredate DATE, sal NUMBER(7,2), comm NUMBER(7,2), deptno NUMBER(2) ) / CREATE OR REPLACE TYPE type_emp IS TABLE OF type_emp_row; / CREATE OR REPLACE FUNCTION f_get_emp(p_deptno NUMBER) RETURN type_emp PIPELINED AS v_emp type_emp_row; BEGIN FOR cur IN (SELECT * FROM scott.emp WHERE deptno = p_deptno) LOOP v_emp := type_emp_row(cur.empno, cur.ename, cur.job, cur.mgr, cur.hiredate, cur.sal, cur.comm, cur.deptno); PIPE ROW(v_emp); END LOOP; END; SQL> select * From table(f_get_emp(10)); EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO ---------- ---------- --------- ---------- ----------- ---------- ---------- ---------- 7782 CLARK MANAGER 7839 1981/6/9 2450 10 7839 KING PRESIDENT 1981/11/17 5000 10 7934 MILLER CLERK 7782 1982/1/23 1300 10

解决方案

方案1:返回数组

返回数组,并用unnest()代替table()

1、函数中返回数组

1.1 函数中循环处理

适合在循环中增加逻辑处理

CREATE TYPE type_emp_row AS ( empno NUMBER(4), ename VARCHAR2(10), job VARCHAR2(9), mgr NUMBER(4), hiredate DATE, sal NUMBER(7,2), comm NUMBER(7,2), deptno NUMBER(2) ); CREATE TYPE type_emp IS TABLE OF type_emp_row; CREATE OR REPLACE FUNCTION f_get_emp(p_deptno NUMBER) RETURN type_emp AS v_emp type_emp_row; res_emp type_emp := type_emp(); BEGIN FOR cur IN (SELECT * FROM scott.emp WHERE deptno = p_deptno) LOOP v_emp := type_emp_row(cur.empno, cur.ename, cur.job, cur.mgr, cur.hiredate, cur.sal, cur.comm, cur.deptno); res_emp.extend; res_emp(res_emp.last)=v_emp; END LOOP; return res_emp; END; / select * from unnest(f_get_emp(10)); empno | ename | job | mgr | hiredate | sal | comm | deptno -------+--------+-----------+------+---------------------+---------+------+-------- 7782 | CLARK | MANAGER | 7839 | 1981-06-09 00:00:00 | 2450.00 | | 10 7839 | KING | PRESIDENT | | 1981-11-17 00:00:00 | 5000.00 | | 10 7934 | MILLER | CLERK | 7782 | 1982-01-23 00:00:00 | 1300.00 | | 10 (3 rows)

1.2 函数中批量处理

不能在循环中增加逻辑处理,可以批量返回

CREATE TYPE type_emp_row AS ( empno NUMBER(4), ename VARCHAR2(10), job VARCHAR2(9), mgr NUMBER(4), hiredate DATE, sal NUMBER(7,2), comm NUMBER(7,2), deptno NUMBER(2) ); CREATE TYPE type_emp IS TABLE OF type_emp_row; / CREATE OR REPLACE FUNCTION f_get_emp(p_deptno NUMBER) RETURN type_emp AS res_emp type_emp := type_emp(); BEGIN SELECT * bulk collect into res_emp FROM scott.emp WHERE deptno = p_deptno; return res_emp; END; / select * from unnest(f_get_emp(10));

2、包中返回数组

方式同上面一样,只是代码放在包中,不需要单独定义TYPE对象

2.1 包中循环处理

适合在循环中增加逻辑处理

CREATE OR REPLACE PACKAGE scott.pkg_emp AS TYPE type_emp_row IS RECORD ( empno NUMBER(4), ename VARCHAR2(10), job VARCHAR2(9), mgr NUMBER(4), hiredate DATE, sal NUMBER(7,2), comm NUMBER(7,2), deptno NUMBER(2) ); TYPE type_emp IS TABLE OF type_emp_row; FUNCTION f_get_emp(p_deptno NUMBER) RETURN type_emp; END pkg_emp; / CREATE OR REPLACE PACKAGE BODY scott.pkg_emp AS FUNCTION f_get_emp(p_deptno NUMBER) RETURN type_emp AS v_emp type_emp_row; res_emp type_emp := type_emp(); BEGIN FOR cur IN (SELECT * FROM scott.emp WHERE deptno = p_deptno) LOOP v_emp.empno := cur.empno; v_emp.ename := cur.ename; v_emp.job := cur.job; v_emp.mgr := cur.mgr; v_emp.hiredate := cur.hiredate; v_emp.sal := cur.sal; v_emp.comm := cur.comm; v_emp.deptno := cur.deptno; res_emp.extend; res_emp(res_emp.last) := v_emp; END LOOP; RETURN res_emp; END f_get_emp; END pkg_emp; / SELECT * FROM unnest(scott.pkg_emp.f_get_emp(10));

2.2 包中批量处理

不能在循环中增加逻辑处理,可以批量返回

CREATE OR REPLACE PACKAGE scott.pkg_emp AS TYPE type_emp_row IS RECORD ( empno NUMBER(4), ename VARCHAR2(10), job VARCHAR2(9), mgr NUMBER(4), hiredate DATE, sal NUMBER(7,2), comm NUMBER(7,2), deptno NUMBER(2) ); TYPE type_emp IS TABLE OF type_emp_row; FUNCTION f_get_emp(p_deptno NUMBER) RETURN type_emp; END pkg_emp; / CREATE OR REPLACE PACKAGE BODY scott.pkg_emp AS FUNCTION f_get_emp(p_deptno NUMBER) RETURN type_emp AS v_emp type_emp_row; res_emp type_emp := type_emp(); BEGIN SELECT * bulk collect into res_emp FROM scott.emp WHERE deptno = p_deptno; RETURN res_emp; END f_get_emp; END pkg_emp; / SELECT * FROM unnest(scott.pkg_emp.f_get_emp(10));

方案2:表函数

2.1 自定义返回类型

自定义返回类型,并且可通过循环处理数据

drop function if exists scott.f_get_emp; CREATE OR REPLACE FUNCTION scott.f_get_emp(p_deptno NUMBER) RETURNS TABLE ( empno INTEGER, ename VARCHAR(10), job VARCHAR(9), mgr INTEGER, hiredate DATE, sal NUMERIC(7,2), comm NUMERIC(7,2), deptno INTEGER ) AS $$ BEGIN FOR cur IN (SELECT * FROM scott.emp WHERE deptno = p_deptno) LOOP empno :=cur.empno ; ename :=cur.ename ; job :=cur.job ; mgr :=cur.mgr ; hiredate :=cur.hiredate ; sal :=cur.sal ; comm :=cur.comm ; deptno :=cur.deptno ; RETURN NEXT; END LOOP; END; $$ LANGUAGE plpgsql; SELECT * FROM scott.f_get_emp(10); empno | ename | job | mgr | hiredate | sal | comm | deptno -------+--------+-----------+------+---------------------+---------+------+-------- 7782 | CLARK | MANAGER | 7839 | 1981-06-09 00:00:00 | 2450.00 | | 10 7839 | KING | PRESIDENT | | 1981-11-17 00:00:00 | 5000.00 | | 10 7934 | MILLER | CLERK | 7782 | 1982-01-23 00:00:00 | 1300.00 | | 10 (3 rows)

2.2 返回与表结构一样的数据

返回列与表结构一样,直接使用setof方式,可在循环中处理数据

drop function if exists scott.f_get_emp; CREATE OR REPLACE FUNCTION scott.f_get_emp(p_deptno NUMBER) RETURNS setof scott.emp AS $$ BEGIN FOR emp_row IN (SELECT * FROM scott.emp WHERE deptno = p_deptno) LOOP -- 使用 RETURN NEXT 返回结果集中的一行 RETURN NEXT emp_row; END LOOP; END; $$ LANGUAGE plpgsql; SELECT * FROM scott.f_get_emp(10);

2.3 RETURN QUERY

直接返回查询结果,中间不做处理,也可以同2.1一样自定义返回类型

drop function if exists scott.f_get_emp; CREATE OR REPLACE FUNCTION scott.f_get_emp(p_deptno NUMBER) RETURNS setof scott.emp AS $$ BEGIN RETURN QUERY SELECT * FROM scott.emp e WHERE deptno = p_deptno; END; $$ LANGUAGE plpgsql; SELECT * FROM scott.f_get_emp(10);
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论