曾经遇到过这样一个需求:要求为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 - 为子查询提供动态结果集的更多相关文章

  1. 【Oracle】曾经的Oracle学习笔记(4-7)多表联合查询,子查询,动态条件查询

    一.多表联合查询 二.子查询 三.动态条件查询 LESSON 4 Displaying Data from Multiple Tables------------------------------- ...

  2. Oracle 之——子查询 DDL DML 集合 及其他数据对象

    Oracle 学习笔记(二) 知识概要: 1.子查询 2.集合操作 3.DML语句操作 4.其他数据库对象 1.子查询 查询工资比SCOTT高的员工信息 1  select * 2  from emp ...

  3. Oracle 通过子查询批量添加、修改表数据

    1.通过查询快速创建表 create table test1(id,job,mgr,sal) as () ) ---这是一个分页查询 ok,表创建成功 2.通过查询快速创建视图 create or r ...

  4. oracle数据库子查询的结果需要使用多次解决办法

    with c as (select a.trandt,sum(a.tranam) tranam from tran a group by a.trandt )--将子查询抽取出来,以后可以直接用.该方 ...

  5. Oracle【子查询】

    Oracle子查询:当一个查询依赖于另外一个查询的结果的时候,就需要使用子查询.单行子查询 :筛选条件不明确,需要执行一次查询且查询结果只有一个字段且字段值只有一个.注意:where子句中允许出现查询 ...

  6. Oracle之子查询:Top-N问题

    学习了SQL子查询,遇到个Top-N问题,即:加入有张工资表(这里使用Oracle SCOTT用户的emp表),需要查找工资最高的3个员工信息,以下列格式输出: 乍眼一看,这很简单啊,对sal进行排序 ...

  7. Oracle Day04 子查询

    1.子查询解决什么问题: 当一个简单的查询查询不到结果的时候,可以使用子查询来丰富查询的条件以达到显示结果的目的. 子查询的格式: 用一个小括号包含,然后在里面写sql语句2.子查询的注意事项: 1) ...

  8. oracle之子查询、创建用户、创建表、约束

      子查询                                    子查询可以分为单行子查询和多行子查询   单行子查询           [1] 将一个查询的结果作为另外一个查询的条 ...

  9. 数据库Oracle的子查询练习

    1.写一个查询显示与 Zlotkey 的 在同一部门的雇员的 last name和 hire date,结果中不包括 Zlotkey --1.写一个查询显示与 Zlotkey 的 在同一部门的雇员的 ...

随机推荐

  1. C#字符串转UNICODE

    public static string StringToUnicode(string s)//字符串转UNICODE代码 { char[] charbuffers = s.ToCharArray() ...

  2. Android - Android Studio 3.0去掉方法参数提示

    升级到3.0之后,最明显的一个就是在调用方法的时候多了一个参数提示.有利有弊,看着不是很舒服.就想去掉. 提示样式如下: 去掉提示: 原文地址: https://blog.csdn.net/stude ...

  3. 队列的实现——java

    同样实现方法有两种: 1. 数组的实现,可以存储任意类型的数据(略): 2. Java的 Collection集合 中自带的"队列"(LinkedList)的示例: import ...

  4. Flask从入门到精通之重定向和用户会话

    最新版的hello.py 存在一个可用性问题.用户输入名字后提交表单,然后点击浏览器的刷新按钮,会看到一个莫名其妙的警告,要求在再次提交表单之前进行确认.之所以出现这种情况,是因为刷新页面时浏览器会重 ...

  5. MongoDB系统CentOS 7.1 crash的排障过程

    [作者] 王栋:携程技术保障中心数据库专家,对数据库疑难问题的排查和数据库自动化智能化运维工具的开发有强烈的兴趣. [问题描述] 最近我们有多台MongoDB的服务器CentOS 7.1系统发生了cr ...

  6. 用 TensorFlow 实现 k-means 聚类代码解析

    k-means 是聚类中比较简单的一种.用这个例子说一下感受一下 TensorFlow 的强大功能和语法. 一. TensorFlow 的安装 按照官网上的步骤一步一步来即可,我使用的是 virtua ...

  7. day 54 linux 常用指令入门

    Linux文件系统结构 Linux目录结构的组织形式和Windows有很大的不同.首先Linux没有“盘(C盘.D盘.E盘)”的概念.已经建立文件系统的硬盘分区被挂载到某一个目录下,用户通过操作目录来 ...

  8. Java爬虫——Gecco简单入门程序(根据下一页一直爬数据)

    为了完成作业,所以学习了一下爬虫Gecco,这个爬虫集合了以往所有的爬虫的特点,但是官方教程中关于Gecco的教程介绍的过于简单,本篇博客是根据原博客的地址修改的,原博客中只有程序的截图,而没有给出一 ...

  9. 剑指offer四十九之把字符串转换成整数

    一.题目 将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数. 数值为0或者字符串不是一个合法的数值则返回0 二.思路 详见代码. 三.代码 public class Solution { ...

  10. 简述ARP请求过程(同一子网和不同子网)

    1. 同一子网 主机A在准备构造链路层以太网帧头时,首先根据目的IP去查找ARP表,如果找到对应项,则直接得到目的MAC地址,如果没有查到才执行上面所说的ARP广播请求.这样做是为了最大限度地减少广播 ...