DBMS_SQL 执行查询示例
通常情况下,需要动态执行查询语句尽量使用语法更简洁的 OPEN {SYS_REFCURSOR} FOR ... 或 EXECUTE IMMEDIATE ...
但当查询语句的列或绑定变量无法确定数量或类型时,还是需要使用更加灵活的 DBMS_SQL 包,下面是使用 DBMS_SQL 包执行列数量可变的查询示例;一个典型的应用场景就是报表的生成,因为我们可能无法事先知道这个报表有多少列。
DECLARE
-- 可变列数的报表查询编程示例
l_Cursor_Id INTEGER;
l_Col_Count INTEGER;
l_Desc_Tbl2 Dbms_Sql.Desc_Tab2;
l_Ret INTEGER;
l_Row_Count BINARY_INTEGER := 0;
l_Row_Index BINARY_INTEGER := 1;
c_Bulk_Size CONSTANT BINARY_INTEGER := 2; -- 每次提取的记录数
-- 报表的每一列最终都是 VARCHAR2 类型
TYPE Col_Val_Tbl_Type IS TABLE OF Dbms_Sql.Varchar2_Table INDEX BY PLS_INTEGER;
l_Col_Val_Tbl Col_Val_Tbl_Type;
BEGIN
-- 打开并解析查询语句
l_Cursor_Id := Dbms_Sql.Open_Cursor;
Dbms_Sql.Parse(l_Cursor_Id,
'SELECT ''X'' M, ''Y'' M FROM DUAL WHERE DUMMY = :T_DUMMY
UNION ALL SELECT ''C'', ''D'' FROM DUAL
UNION ALL SELECT ''E'', ''F'' FROM DUAL',
Dbms_Sql.Native);
-- 根据查询语句的列取出所有值
Dbms_Sql.Describe_Columns2(l_Cursor_Id, l_Col_Count, l_Desc_Tbl2);
FOR i IN 1 .. l_Col_Count LOOP
l_Col_Val_Tbl(i)(0) := NULL;
Dbms_Sql.Define_Array(c => l_Cursor_Id,
Position => i,
c_Tab => l_Col_Val_Tbl(i),
Cnt => c_Bulk_Size,
Lower_Bound => l_Row_Index);
END LOOP;
-- 绑定变量并执行
Dbms_Sql.Bind_Variable(l_Cursor_Id, ':T_DUMMY', 'X');
l_Ret := Dbms_Sql.Execute(l_Cursor_Id); -- 返回 DML 语句的修改行数,此处不使用
-- 遍历查询结果
LOOP
l_Row_Count := l_Row_Count + Dbms_Sql.Fetch_Rows(l_Cursor_Id);
EXIT WHEN l_Row_Count < l_Row_Index; -- 取出记录后总行数未增加
-- Dbms_Output.Put_Line('FETCH: ' || (l_Row_Count - l_Row_Index + 1));
-- 取每一列的值
FOR j IN 1 .. l_Col_Count LOOP
Dbms_Sql.Column_Value(l_Cursor_Id, j, l_Col_Val_Tbl(j));
END LOOP;
-- 遍历每一行
FOR i IN l_Row_Index .. l_Row_Count LOOP
FOR j IN 1 .. l_Col_Count LOOP
-- 遍历每一列
Dbms_Output.Put(l_Col_Val_Tbl(j) (i) || ' ');
END LOOP;
Dbms_Output.Put_Line('');
END LOOP;
EXIT WHEN l_Row_Count - l_Row_Index + 1 < c_Bulk_Size; -- 本次取出的行数小于指定的值,不进行下次取值
l_Row_Index := l_Row_Count + 1;
END LOOP;
-- 关闭
IF Dbms_Sql.Is_Open(l_Cursor_Id) THEN
Dbms_Sql.Close_Cursor(l_Cursor_Id);
END IF;
END;
DBMS_SQL 包还提供了两个很棒的函数用于在 DBMS_SQL 的 CURSOR_NUMBER 和 SYS_REFCURSOR 之间切换,我们可以充分利用二者的长处:CURSOR_NUMBER 更灵活,SYS_REFCURSOR 更简洁。
例如上述示例在绑定变量上没有不确定性,只需要动态变化查询到的列,那么可以先使用语法简洁的 SYS_REFCURSOR 打开查询,然后切到 CURSOR_NUMBER 对列进行分析。
这两个函数的定义及说明如下:
function to_refcursor(cursor_number in out integer) return sys_refcursor;
CURSOR_NUMBER 必须是一个已经执行过(调用过 DBMS_SQL.EXECUTE)的查询,调用后游标的控制权转移到返回的 SYS_REFCURSOR 变量上,后续应且仅应 CLOSE SYS_REFCURSOR;
function to_cursor_number(rc in out sys_refcursor) return integer;
SYS_REFCURSOR 必须是一个已经打开(执行过 OPEN ... FOR ..)的查询,调用后游标的控制权转移到返回的 CURSOR_NUMBER 变量上,后续应且仅应 DBMS_SQL.CLOSE_CURSOR(CURSOR_NUMBER);
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Spring Boot数据校验
数据校验是一个相当重要的环节,使用Spring Boot 进行数据校验。 添加校验依赖 全部依赖文件如下 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion>
- 下一篇
八张图彻底了解JDK8 GC调优秘籍-附PDF下载
简介 JVM的参数有很多很多,根据我的统计JDK8中JVM的参数总共有1853个,正式的参数也有680个。 这么多参数带给我们的是对JVM的细粒度的控制,但是并不是所有的参数都需要我们自己去调节的,我们需要关注的是一些最常用的,对性能影响比较大的GC参数即可。 为了更好的让大家理解JDK8中 GC的调优的秘籍,这里特意准备了八张图。在本文的最后,还附带了一个总结的PDF all in one文档,大家把PDF下载回去,遇到问题就看两眼,不美吗? 分代垃圾回收器的内存结构 为了更好的提升GC的效率,现代的JVM都是采用的分代垃圾回收的策略(ZGC不是)。 java运行时内存可以分为JVM内存和非JVM内存。 JVM内存又可以分为堆内存和非堆内存。 堆内存大家都很熟悉了,YoungGen中的Eden,Survivor和OldGen。 非堆内存中存储的有thread Stack,Code Cache, NIO Direct Buffers,Metaspace等。 注意这里的Metaspace元空间是方法区在JDK8的实现,它是在本地内存中分配的。 JDK8中可用的GC JDK8中到底有哪些可...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Red5直播服务器,属于Java语言的直播服务器
- CentOS7,CentOS8安装Elasticsearch6.8.6
- CentOS8编译安装MySQL8.0.19
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS6,CentOS7官方镜像安装Oracle11G
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- CentOS8安装Docker,最新的服务器搭配容器使用