热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

PL/SQLarraysv7

TurningaPLSQLarrayintoanSQLstate


JL Computer Consultancy






PL/SQL arrays as Cursors (Oracle 7.3)



July 1999






If you have created an array in PL/SQL is there a way to send it back to SQL
as a cursor in version 7 of Oracle ? The answer is yes but it's very inefficient.
The following package gives you an example of how the method works. A much better method is available if you have Oracle 8 with
the Object option.

There are two steps in Oracle 7.3. First you need some way of selecting an
arbitrarily long list of integers with no gaps. You could do this with a silly
statement like 'select rownum from all_objects', but I prefer to create a
limited table of one column which I populate with a one-off SQL statement. e.g:

               create table sequential_numbers

>               unrecoverable

>               pctfree 0

>               as

>               select rownum n from all_objects

>               ;

You then need to write a package with a function to populate the array, a
function to count the number of rows in the array, and a function to return one
'column' from each row in the array. Once you have these, you can write an SQL
script like:

              

>               variable tab_size number

>               execute :tab_size := array_as_cursor.populate_array;

>               select

>                       n,

>                       array_as_cursor.number_column(n),

>                       substr(array_as_cursor.varchar2_column(n),1,20)

>               from

>                       sequential_numbers

>               where n <= :tab_size

/*>             where n <= (select array_as_cursor.current_size from dual)>   */

               ;

As you can see the method is a little clumsy, and for every item of data you
want you have to call a function to get a value - the CPU cost is quite
dramatic, so don't use this method for large amounts of data.

Note: if you don't want to use the bind variable method then you MUST use a
subquery select from dual to return the current size just once, otherwise a construct
like 'n <= array_as_cursor.current_size' will result in the function being
called once for every row in the sequential_numbers table.

Note also the substr() function used on the varchar2 function - pl/sql
functions do NOT return bounded values so the default return column is assumed
to be VARCHAR2(2000), similarly the returned number column is assumed to be
just NUMBER, and not NUMBER(p,s). You need to impose your own bounds in the SQL
itself (although you could protect end-users by creating a view to impose these
bounds)..





The demonstration package

rem

rem     Script:>        c_pack.sql

rem>     Dated;         July-1999

rem>     Author:        Jonathan Lewis

rem>     Oracle:        7.3.3.5

rem>     Purpose:       Package to demonstrate arrays returned by cursors in v7

rem

rem>     Notes:

rem     This is very CPU intensive, and should

rem>     be used only for very small sets of data.

rem

rem>     To stick to the lowest version of PL/SQL, it avoids using

rem>     records for the array. Also, because Oracle Corp. forgot to put

rem>     the 'restrict_references' pragma into the definitions of

rem>     functions used to count arrays, the method for counting

rem>     the content of the array is somewhat naive.

rem

rem>     It would be nice to be able to select where

rem

rem>            n <= (select array_as_cursor.populate from dual)

rem

rem>     to populate the array and return the count in one step,

rem>     but in recent versions of PL/SQL this cannot be done as the

rem>     function used in the sub-query may not write a package state

rem>     (WNPS) so it cannot populate the array.  (This check is

rem>     missed, I think, in earlier versions of PL/SQL:  a function

rem>     could  write its OWN package state and still be given the

rem>     purity level WNPS without causing a compile error).  You can

rem>     also do this in Oracle 8.1 - but there are better ways of

rem>     turning arrays into cursors in 8.1 anyway.

rem

create or replace package array_as_cursor as

>        function populate_array return number;

>        pragma restrict_references(populate_array, wnds);

>        function current_size return number;

>        pragma restrict_references(current_size, wnds, rnds, wnps);

>        function number_column(i in integer) return number;

>        pragma restrict_references(number_column ,wnds, rnds ,wnps);

>        function varchar2_column(i in integer) return varchar2;

>        pragma restrict_references(varchar2_column, wnds, rnds, wnps);

end;

/

create or replace package body array_as_cursor as

type>    t_numbers      is table of number index by binary_integer;

type>    t_varchar2s    is table of varchar2(2000) index by binary_integer;

v_numbers>      t_numbers;

v_empty_numbers> t_numbers;

v_varchar2s>            t_varchar2s;

v_empty_varchar2s>      t_varchar2s;

v_count> number := 0;

function populate_array return number is

begin

>        v_varchar2s := v_empty_varchar2s;

>        v_numbers := v_empty_numbers;

>        v_count := 0;

-->      Do what you want to fill arrays here e.g.

>        for r in (

>                       select table_name, num_rows

>                       from user_tables

>                       where rownum <= 5

>        ) loop

               v_count := v_count + 1;

>               v_numbers(v_count) := r.num_rows;

>               v_varchar2s(v_count) := r.table_name;

>        end loop;

>        return v_count;

end;

>       

function current_size return number is

begin

>        return v_count;

end;

function number_column(i in integer) return number is

begin

>        return v_numbers(i);

exception

>        when no_data_found then

>               return null;

end;

function varchar2_column(i in integer) return varchar2 is

begin

>        return v_varchar2s(i);

exception

>        when no_data_found then

>               return null;

end;

end;

/

 




Output from the demonstration SELECT statement above

PL/SQL procedure successfully completed.

        N ARRAY_AS_CURSOR.NUMBER_COLUMN(N) SUBSTR(ARRAY_AS_CURS                                    

--------- -------------------------------- --------------------                                    

        1                               33 CUSTOMER                                                

        2                               11 DEPARTMENT                                               

        3                               32 EMPLOYEE                                                

        4                              271 ITEM                                                    

        5                                6 JOB                                                     







推荐阅读
  • 本文深入探讨 MyBatis 中动态 SQL 的使用方法,包括 if/where、trim 自定义字符串截取规则、choose 分支选择、封装查询和修改条件的 where/set 标签、批量处理的 foreach 标签以及内置参数和 bind 的用法。 ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • 深入解析Android自定义View面试题
    本文探讨了Android Launcher开发中自定义View的重要性,并通过一道经典的面试题,帮助开发者更好地理解自定义View的实现细节。文章不仅涵盖了基础知识,还提供了实际操作建议。 ... [详细]
  • 深入理解 Oracle 存储函数:计算员工年收入
    本文介绍如何使用 Oracle 存储函数查询特定员工的年收入。我们将详细解释存储函数的创建过程,并提供完整的代码示例。 ... [详细]
  • 本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ... [详细]
  • Explore how Matterverse is redefining the metaverse experience, creating immersive and meaningful virtual environments that foster genuine connections and economic opportunities. ... [详细]
  • Explore a common issue encountered when implementing an OAuth 1.0a API, specifically the inability to encode null objects and how to resolve it. ... [详细]
  • 技术分享:从动态网站提取站点密钥的解决方案
    本文探讨了如何从动态网站中提取站点密钥,特别是针对验证码(reCAPTCHA)的处理方法。通过结合Selenium和requests库,提供了详细的代码示例和优化建议。 ... [详细]
  • 本文基于刘洪波老师的《英文词根词缀精讲》,深入探讨了多个重要词根词缀的起源及其相关词汇,帮助读者更好地理解和记忆英语单词。 ... [详细]
  • 本文介绍了Java并发库中的阻塞队列(BlockingQueue)及其典型应用场景。通过具体实例,展示了如何利用LinkedBlockingQueue实现线程间高效、安全的数据传递,并结合线程池和原子类优化性能。 ... [详细]
  • 深入理解 SQL 视图、存储过程与事务
    本文详细介绍了SQL中的视图、存储过程和事务的概念及应用。视图为用户提供了一种灵活的数据查询方式,存储过程则封装了复杂的SQL逻辑,而事务确保了数据库操作的完整性和一致性。 ... [详细]
  • 深入解析Spring Cloud Ribbon负载均衡机制
    本文详细介绍了Spring Cloud中的Ribbon组件如何实现服务调用的负载均衡。通过分析其工作原理、源码结构及配置方式,帮助读者理解Ribbon在分布式系统中的重要作用。 ... [详细]
  • 前言--页数多了以后需要指定到某一页(只做了功能,样式没有细调)html ... [详细]
  • golang常用库:配置文件解析库/管理工具viper使用
    golang常用库:配置文件解析库管理工具-viper使用-一、viper简介viper配置管理解析库,是由大神SteveFrancia开发,他在google领导着golang的 ... [详细]
  • 本文详细介绍 Go+ 编程语言中的上下文处理机制,涵盖其基本概念、关键方法及应用场景。Go+ 是一门结合了 Go 的高效工程开发特性和 Python 数据科学功能的编程语言。 ... [详细]
author-avatar
晓亮居士_264
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有