Oracle - 为子查询提供动态结果集
曾经遇到过这样一个需求:要求为method传入String,内容如"用户ID0,用户ID1,用户ID2...",然后根据这些ID返回一个结果集作为数据表供别人查询。
SELECT * FROM TBL WHERE ID IN ('用户ID0,用户ID1,用户ID2') 不就可以解决问题吗?
但实际情况是,结果集无法通过一个简单的SELECT就可以得到。
让我明确一下需要解决的问题:
我们给FUNCTION传递这样的一个String参数后如何让它动态RETURN一个结果集供其他SELECT语句使用。
既然我们要返回一个结果集,那便是要得到一个TABLE OF XXX类型,XXX可以是VARCHAR2或者INTEGER或者某个表的%ROWTYPE,但我的情况稍微复杂一点,我要自己创建一个OBJECT TYPE。
于是我们要写的FUNCTION的RETURN类型是这样创建的:
CREATE OR REPLACE TYPE TYP_USER_RECORD AS OBJECT (USER_ID CHAR(40),USER_NUM VARCHAR2(200),CREATE_DATE DATE);
CREATE OR REPLACE TYPE TYP_USER_TBL AS TABLE OF TYP_USER_RECORD;
下面是FUNCTION的创建:
CREATE OR REPLACE FUNCTION REGROUP_USER_BY_USERIDSTR(USERIDSTR IN VARCHAR2)
RETURN TYP_USER_TBL
PIPELINED IS
--参数声明开始
TYPE USER_CURSOR IS REF CURSOR;
USER_INFO_LIST USER_CURSOR; --用来获得检索结果的CURSOR
TYPE USER_ROW IS RECORD(
USER_ID CHAR(40),USER_NUM VARCHAR2(200),CREATE_DATE DATE);
USER_INFO USER_ROW; --用于提取CURSOR中的记录的RECORD
USER_ROW4RESULT TYP_USER_RECORD; --我们要返回的数据集的数据行对象
QUERYSTR VARCHAR2(2000); --拼接后的SELECT语句
--参数声明结束
BEGIN
--此处根据传入的ID进行了各种判断拼接SELECT语句 并给QUERYSTR赋值
OPEN USER_INFO_LIST FOR QUERYSTR; --打开CURSOR
--循环从CURSOR获得结果 并将结果变成TYP_USER_RECORD对象 再将对象放到PIPE里
LOOP
FETCH USER_INFO_LIST INTO USER_INFO;
EXIT WHEN USER_INFO_LIST%NOTFOUND;
USER_ROW4RESULT := TYP_USER_RECORD(USER_INFO.USER_ID,
USER_INFO.USER_NUM,
USER_INFO.CREATE_DATE);
PIPE ROW(USER_ROW4RESULT);
END LOOP;
CLOSE USER_INFO_LIST;
RETURN;
END;
既然RETURN TYPE是TABLE类型的,调用时便可以使用TABLE()函数进行查询。
SELECT * FROM TABLE(REGROUP_USER_BY_USERIDSTR)
另外,本人目前工程中使用的持久化框架是MyBatis,此语句执行无误。
参数虽然可以直接传入SELECT * FROM XX IN ()进行查询,但也可能需要进行截取变成COLLECION,下面是该功能的FUNCTION:
CREATE OR REPLACE TYPE TBL_VARCHAR2 AS TABLE OF VARCHAR2(400);
CREATE OR REPLACE FUNCTION STR2TBL( PARAM_STR IN VARCHAR2 ) RETURN TBL_VARCHAR2
AS
TMP_RECORD LONG DEFAULT PARAM_STR || ',';
ROW_INDEX NUMBER;
TMP_TBL TBL_VARCHAR2 := TBL_VARCHAR2();
BEGIN
LOOP
ROW_INDEX := INSTR( TMP_RECORD, ',' );
EXIT WHEN (NVL(ROW_INDEX,0) = 0);
TMP_TBL.EXTEND;
TMP_TBL( TMP_TBL.COUNT ) := LTRIM(RTRIM(SUBSTR(TMP_RECORD,1,ROW_INDEX-1)));
TMP_RECORD := SUBSTR( TMP_RECORD, ROW_INDEX+1 );
END LOOP;
RETURN TMP_TBL;
END;
这种方式的意义可能只有让开发方便了一些,试图用一句SQL拯救世界必将导致各种问题。
为什么会有这种需求,可能是因为数据关系梳理地有些仓促,数据散落在不同的数据表。
无论如何这是一个糟糕的场景。
Oracle - 为子查询提供动态结果集的更多相关文章
- 【Oracle】曾经的Oracle学习笔记(4-7)多表联合查询,子查询,动态条件查询
一.多表联合查询 二.子查询 三.动态条件查询 LESSON 4 Displaying Data from Multiple Tables------------------------------- ...
- Oracle 之——子查询 DDL DML 集合 及其他数据对象
Oracle 学习笔记(二) 知识概要: 1.子查询 2.集合操作 3.DML语句操作 4.其他数据库对象 1.子查询 查询工资比SCOTT高的员工信息 1 select * 2 from emp ...
- Oracle 通过子查询批量添加、修改表数据
1.通过查询快速创建表 create table test1(id,job,mgr,sal) as () ) ---这是一个分页查询 ok,表创建成功 2.通过查询快速创建视图 create or r ...
- oracle数据库子查询的结果需要使用多次解决办法
with c as (select a.trandt,sum(a.tranam) tranam from tran a group by a.trandt )--将子查询抽取出来,以后可以直接用.该方 ...
- Oracle【子查询】
Oracle子查询:当一个查询依赖于另外一个查询的结果的时候,就需要使用子查询.单行子查询 :筛选条件不明确,需要执行一次查询且查询结果只有一个字段且字段值只有一个.注意:where子句中允许出现查询 ...
- Oracle之子查询:Top-N问题
学习了SQL子查询,遇到个Top-N问题,即:加入有张工资表(这里使用Oracle SCOTT用户的emp表),需要查找工资最高的3个员工信息,以下列格式输出: 乍眼一看,这很简单啊,对sal进行排序 ...
- Oracle Day04 子查询
1.子查询解决什么问题: 当一个简单的查询查询不到结果的时候,可以使用子查询来丰富查询的条件以达到显示结果的目的. 子查询的格式: 用一个小括号包含,然后在里面写sql语句2.子查询的注意事项: 1) ...
- oracle之子查询、创建用户、创建表、约束
子查询 子查询可以分为单行子查询和多行子查询 单行子查询 [1] 将一个查询的结果作为另外一个查询的条 ...
- 数据库Oracle的子查询练习
1.写一个查询显示与 Zlotkey 的 在同一部门的雇员的 last name和 hire date,结果中不包括 Zlotkey --1.写一个查询显示与 Zlotkey 的 在同一部门的雇员的 ...
随机推荐
- SQLite 编译错误 - 试图加载格式不正确的程序
刚开始用SQLite,刚开始写了一个小程序,连接数据库的时候出现了问题,提示试图加载格式不正确的程序, 原因是我当前工程的目标平台是X86,改成Any CPU之后问题就解决了.如下图:
- 《ASP.NET MVC 5 破境之道》:概述
第一节:写作本书的目的 关于笔者 张晓亭(Mike Cheers),1982年出生,内蒙古辽阔的大草原是我的故乡. 没有高学历,没有侃侃而谈的高谈阔论,拥有的就是那一份对技术的执著,对自我价值的追求. ...
- 学习Python中的集合
创建集合 使用工厂方法 set()和 frozenset(): >>> s = set('cheeseshop') >>> s set(['c', 'e', 'h' ...
- WEB-INFO 目录
WEB-INF下面的内容都是只能由服务器级别才能访问,客户端并不能访问. 转发就是服务器级别,浏览器的地址不会变,因为,客户端发送一个请求,服务器受理之后,发现要请求内容还要再去别的请求,那么转发就是 ...
- 怎么在一台电脑上同时启动多个tomcat
怎么在一台电脑上同时启动多个tomcat? 应用场景: 一台电脑,需要同时部署多个tomcat,用于部署不同的系统 分布式系统,一个系统,同时需要开启多个tomcat,因为分布式系统可能会有多个war ...
- 散列表碰撞处理、开链法、HashTable散列
散列表碰撞处理.开链法.HashTable散列 /** * 散列表碰撞处理.开链法.HashTable散列. * 将数组里的元素位置,也设置为数组,当两个数据的散列在同一个位置时, * 就可以放在这个 ...
- Qt: QTimer和QThread
让QTimer 跑在其他线程. 一般写法如下. 1. 在main thread中为worker thread指定定时器. QThread* thread = new QThread(this); th ...
- webpack使用来打包前端代码
使用webpack打包js文件(隔行变色案例) 1.webpack安装的两种方式 运行npm i webpack -g全局安装webpack,这样就能在全局使用webpack的命令 在项目根目录中运行 ...
- Android Kotlin开发之使用Butterknife注意要点
使用kotlin-kapt插件 依赖由java的annotationProcessor改为kapt 在使用控件绑定使用时,网上搜使用方法,不知道被哪个家伙带坑里了. //错误用法 @BindView( ...
- Maven 学习笔记(一)
什么是 maven? 对于已经使用过 maven 的用户来说 maven 就是一个架构工具,使用它可以将代码构建成一个可发布的工具.当然也有人会说maven是一个项目管理的工具.当然各有各的说法,那么 ...