MogDB如何兼容Oracle的管道函数

在之前很多数据库国产化改造项目中,我们遇到了很多难题,其中一个难点在于重度使用Oracle的一些用户使用了大量的管道函数(pipeline)。在之前的版本中,由于MogDB还不支持pipeline,因此给我们造成了不小的麻烦。但是凭借团队极强的代码改写和优化能力,我们能够完美的解决这个问题。

实际上主要是因为MogDB 5.0就已经支持了table()函数,因此要解决这个问题,也不算太困难。

这里给大家一些演示例子。

构造测试用例

如下是一段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;

调用上述table函数执行的结果如下所示:

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

那么上述代码如果要移植到MogDB 有哪些解决方案呢? 这里分享几个。

改写方案1

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
   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;
/

改写完毕之后,我们来看看查询效果。

xxdb=> select * from table(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区别不太大,主要是函数部分与上面稍有区别,如下是改写后的代码,以供参考。

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
   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;


当然如果这里我们不使用table()函数,是否还有解决方案呢?答案是肯定的,那就是直接改为表函数的方式。针对不使用table()函数的方式,这里我们也提供了2个改写的方法。

不使用table() 改写方案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;

这里来看看改写的效果如何。

xxdb=> 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种处理方案,这也共享一下改写示例代码,供大家参考,如下所示。

不使用table() 改写方案2

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;

不使用table() 改写方案3

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;

对于前面提到的table()函数的用法说明,大家可以参考: https://docs.mogdb.io/zh/mogdb/v5.0/support-table-function#%E7%89%B9%E6%80%A7%E7%BA%A6%E6%9D%9F

本文由 mdnice 多平台发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/580347.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用QTcpSocket

(1)客户端每隔10ms向服务器发送一次数字字符串&#xff0c;从0开始。 #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include <QTcpSocket> #include <QLabel> #include <QTimer> namespace Ui { class MainWindow; }class Mai…

MAVEN的安装与配置

MAVEN的安装与配置 1 简介 1.1 什么是MAVEN? Maven是一个项目构建及管理工具&#xff0c;开发团队几乎不用花多少时间就能够自动完成工程的基础构建配置&#xff0c; Maven 使用了一个标准的目录结构在不同开发工具中也能实现项目结构的统一。Maven提供了清理&#xff0c;编…

【Vue】组件化编程

定义 实现应用中局部功能代码和资源的集合 为什么要用组件化编程? 传统方式编写:依赖关系混乱,不好维护,且代码复用率不高 模块化编写:只关注解决js,复用js,简化js的编写与效率 组件方式编写:好维护、复用率更高、提高运行效率 在组件出现之前,我们开发基本都是用htm…

【综述】DSP处理器芯片

文章目录 TI DSP C2000系列 TMS320F28003X 典型应用 开发工具链 参考资料 TI DSP TI C2000系列 控制领域 TI C5000系列 通信领域 TI C6000系列 图像领域 C2000系列 第三代集成了C28浮点DSP内核&#xff0c;采用了65nm工艺&#xff08;上一代180nm&#xff09; 第四代正在…

PyCharm 无法运行的解决方案

问题&#xff1a; PyCharm 无法运行&#xff0c;该怎么办&#xff1f; 解决方案&#xff1a; 1. 检查 Python 解释器 确保已为 PyCharm 配置正确的 Python 解释器。打开 PyCharm&#xff0c;转到“文件”>“设置”>“项目”>“Python 解释器”。选择所需的 Python …

怎么在海外平台买东西?Nike海淘攻略

不管在那个海外平台买东西首先要进入官网&#xff0c;最好注册一个gmail账号&#xff0c;这样使用范围比较宽广&#xff0c;在对应平台进行注册账号&#xff0c;比如亚马逊、ebay、Etsy等等 一、Nike海淘攻略 1、然后如果已经会员的话直接输入账号密码登录&#xff0c;如果不…

AI大模型探索之路-训练篇3:大语言模型全景解读

文章目录 前言一、语言模型发展历程1. 第一阶段&#xff1a;统计语言模型&#xff08;Statistical Language Model, SLM&#xff09;2. 第二阶段&#xff1a;神经语言模型&#xff08;Neural Language Model, NLM&#xff09;3. 第三阶段&#xff1a;预训练语言模型&#xff08…

顺通拖鞋ERP企业销售管理系统:驱动销售业绩飙升的利器

顺通企业销售管理系统通过集成客户信息、销售流程、数据分析等功能&#xff0c;帮助企业全面提升销售效率和业绩&#xff0c;成为驱动销售业绩飙升的利器。此外&#xff0c;系统还支持销售流程的可视化展示&#xff0c;使销售人员能够清晰地了解销售进展&#xff0c;及时调整销…

短视频账号矩阵系统===4年技术源头打磨

短视频矩阵系统技术源头打磨需要从多个方面入手&#xff0c;以下是一些建议&#xff1a; 1. 基础技术研发&#xff1a;不断投入资金和人力进行基础技术研发&#xff0c;包括但不限于视频处理、人工智能、大数据等技术&#xff0c;以提高短视频矩阵系统的性能和稳定性。 2. 优化…

JAVA面试八股文之JVM

JVM JVM由那些部分组成&#xff0c;运行流程是什么&#xff1f;你能详细说一下 JVM 运行时数据区吗&#xff1f;详细介绍一下程序计数器的作用&#xff1f;你能给我详细的介绍Java堆吗?什么是虚拟机栈&#xff1f;栈内存溢出情况&#xff1f;堆栈的区别是什么吗&#xff1f;解…

深入理解分布式事务② ---->分布式事务基础(MySQL 的 4 种事务隔离级别【读未提交、读已提交、可重复读、串行化】的最佳实践演示)详解

目录 深入理解分布式事务② ----&#xff1e;分布式事务基础&#xff08;MySQL 的 4 种事务隔离级别【读未提交、读已提交、可重复读、串行化】的最佳实践演示&#xff09;详解1、MySQL 事务基础1-1&#xff1a;MySQL 中 4 种事务隔离级别的区别1-2&#xff1a;MySQL 中 4 种事…

Qt使用OPCUA

假如想在Qt下使用OPCUA通讯&#xff0c;貌似大家都是倾向于使用【qtopcua】这个库。但是在Qt6之前&#xff0c;假如想使用这个库&#xff0c;还得自己编译&#xff0c;比较繁琐。假如想开箱即用&#xff0c;而且没有使用太复杂的功能的话&#xff0c;其实可以直接使用open62541…

2024年最新一线互联网企业高级软件测试工程师面试题大全

1、功能测试 功能测试是游戏测试中跟“玩游戏”最相关的一个环节。 当然这里的“玩”不是要真的让你感受快乐&#xff0c;而是要通过“玩”游戏&#xff0c;发现存在的问题或不合理的地方。因此&#xff0c;这个“玩”的过程基本不会感受到游戏的乐趣。事实上&#xff0c;每一次…

决策树学习笔记

一、衡量标准——熵 随机变量不确定性的度量 信息增益&#xff1a;表示特征X使得类Y的不确定性减少的程度。 二、数据集 14天的打球情况 特征&#xff1a;4种环境变化&#xff08;天气、温度等等&#xff09; 在上述数据种&#xff0c;14天中打球的天数为9天&#xff1b;不…

LVGL移植

Lvgl介绍 LVGL是一个开源的图形库&#xff0c;专为嵌入式系统设计。它提供了丰富的图形元素和功能&#xff0c;可以帮助开发者快速构建现代化的用户界面。LVGL具有跨平台的特性&#xff0c;支持多种操作系统和硬件平台&#xff0c;包括ARM Cortex-M&#xff0c;ESP32&#xff…

基于springboot+vue+Mysql的漫画网站

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

等保测评与信息安全管理体系认证的区别

区别一、标准以及性质 等保测评以《中华人民共和国计算机信息系统安全保护条例》为基础&#xff0c;结合一系列的政策和标准&#xff0c;对信息安全水平进行评估。而安全管理系统的认证&#xff0c;是资讯安全管理系统的一种规范&#xff0c;本身并不具备强制性质。企业可根据…

这么全的权限系统设计方案,不值得收藏吗?

1 为什么需要权限管理 日常工作中权限的问题时时刻刻伴随着我们&#xff0c;程序员新入职一家公司需要找人开通各种权限&#xff0c;比如网络连接的权限、编码下载提交的权限、监控平台登录的权限、运营平台查数据的权限等等。 在很多时候我们会觉得这么多繁杂的申请给工作带…

未来想从事Linux 后台开发,需要学习linux内核吗?

先列出主要观点&#xff0c;有时间再补充细节&#xff1a; “学习Linux内核”对不同的人有不同的含义&#xff0c;学习方法、侧重点、投入的精力也大不相同。我大致分三类&#xff1a;reader、writer、hacker。reader 就是了解某个功能在内核的大致实现 how does it work&…

ZIP压缩输入流(将文件压缩为ZIP文件)

文章目录 前言一、ZIP压缩输入流是什么&#xff1f;二、使用介绍 1.使用方法2.实操展示总结 前言 该篇文章将会介绍如何使用java代码将各种文件&#xff08;文件夹&#xff09;的资源压缩为一个ZIP压缩包。通过java.util包中的ZipOutputStream类来实现。并且需要自定义压缩方法…
最新文章