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拯救世界必将导致各种问题。
为什么会有这种需求,可能是因为数据关系梳理地有些仓促,数据散落在不同的数据表。
无论如何这是一个糟糕的场景。

时间: 2024-11-08 21:24:27

Oracle - 为子查询提供动态结果集的相关文章

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

一.多表联合查询 二.子查询 三.动态条件查询 LESSON 4 Displaying Data from Multiple Tables-------------------------------------------------------- 查询s_emp表中最大的工资数,并且显示出这个最大工资数的员工名字 select last_name,max(salary)from s_emp; 多表查询 查询多张表的时候会产生笛卡尔积 为了防止笛卡尔积的产生,我们需要使用某些条件把两张表或多张

Oracle【子查询】

Oracle子查询:当一个查询依赖于另外一个查询的结果的时候,就需要使用子查询.单行子查询 :筛选条件不明确,需要执行一次查询且查询结果只有一个字段且字段值只有一个.注意:where子句中允许出现查询语句,该查询语句称为子查询.使用:select 内容 from 表名 where 字段名 比较运算符 子查询语句 1 --查询所有比雇员'CLARK'工资高于员工的信息 2 select * from emp where sal>(select sal from emp where ename='C

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

with c as (select a.trandt,sum(a.tranam) tranam from tran a group by a.trandt )--将子查询抽取出来,以后可以直接用.该方法只适用于oracle,mysql不支持 select c.trandt, sum(d.tranam) from c inner join c d on c.trandt >= d.trandt group by c.trandt select c.trandt, sum(d.tranam) fro

Oracle Day04 子查询

1.子查询解决什么问题: 当一个简单的查询查询不到结果的时候,可以使用子查询来丰富查询的条件以达到显示结果的目的. 子查询的格式: 用一个小括号包含,然后在里面写sql语句2.子查询的注意事项: 1).注意一定要有小括号. 2).一定要注意书写格式,不要混乱. 3). 子查询可以放在select,from ,where having后面.    4). 注意子查询一定不能放在group by的后面. 5). 子查询和主查询可以不是同一张表,只要子查询的结果在主查询中能用就可以. 6). 子查询中

一个例子讲述Oracle Any子查询

问题: 查询出Emp表中比任意一个销售员("SALESMAN")工资低的员工姓名.工作.工资. 分析: 销售员在Emp表中有很多条记录,每个人工资不相等,如果返回"比任意员工的工资还低"的条件,返回比"最高工资还低"即可. 如果用子查询做,子查询中就会返回多条记录.用普通的关系符(>.<等)运行就会出错. 这时候需要用关键字ANY.ANY放在比较运算符后面,表示"任意"的意思. 代码演示:ANY子查询 <sp

一个例子讲通Oracle All子查询

问题: 查询出比所有销售员的工资都高的员工姓名,工作,工资. 分析: ANY可以表示任意的,但这个问题要求比所有销售员工资都高,那么就要使用另外一个关键字ALL. ALL与关系操作符一起使用,表示与子查询中所有元素比较. 代码演示:ALL子查询 <span style="font-size:18px;">SQL> SELECT ENAME,JOB,SAL FROM EMP 2 WHERE SAL>ALL (SELECT SAL FROM EMP WHERE JO

oracle 单行子查询

子查询在SELECT.UPDATE.DELETE语句内部可以出现SELECT语句.内部的SELECT语句结果可以作为外部语句中条件子句的一部分, 也可以作为外部查询的临时表.子查询的类型有: 1. 单行子查询:不向外部返回结果,或者只返回一行结果. 2. 多行子查询:向外部返回零行.一行或者多行结果. 单行子查询代码演示:查询出销售部(SALES)下面的员工姓名,工作,工资.该问题可以用联接查询实现,由于所需的结果信息都在Emp表中, 可以先从Dept表中查询出销售部对应的部门号,然后根据当前部

oracle标量子查询

SQL> conn scott/scott Connected. SQL> create table a (id int,name varchar2(10)); Table created. SQL> create table b (id int,name varchar2(10)); Table created. SQL> insert into a values(1,'a1'); 1 row created. SQL> insert into a values(2,'a2

彻底搞懂oracle的标量子查询

oracle标量子查询和自定义函数有时用起来比较方便,而且开发人员也经常使用,数据量小还无所谓,数据量大,往往存在性能问题. 以下测试帮助大家彻底搞懂标量子查询. SQL> create table a (id int,name varchar2(10)); Table created. SQL> create table b (id int,name varchar2(10)); Table created. SQL> insert into a values (1,'a1'); 1