function dynamic fetch in Oracle

In coding, we often meet some sql queries like ‘ select many cloumns from tablename where condition; ‘. When the number of cloumns is dynamic, we should use ResultSet to achieve in Java. As we all know, the class ResultSet has been defined in Java class library. We can use it to get the result of query with optional cloumns directly. However, we now in Oracle/PLSQL, and if we want to get the same effect as Java, we should get one better way to solve that. You may think about using cursor to achieve you want. Actually, you will realized that‘s not exactly what you think. There is one solution for what we said, the following function makes full use of cursor to get what we want.

create or replace function func_dynamic_fetch
(   p_sql in varchar2,
    p_no_of_cols integer,
    p_return_multiple_row boolean := true)
return anydatalist is
    lc_rs sys_refcursor;
    strlist varchar2List := varchar2List();
    n number := 3;
    code varchar2(32767);
    TYPE ref_cursor IS REF CURSOR;
    rc_         ref_cursor;
    c_          NUMBER;
    i_          NUMBER;
    col_count_  NUMBER;
    desc_tab_   DBMS_SQL.DESC_TAB2;
    col_num  NUMBER;
    n2 number;
    l_any_list anydatalist;
    l_types varchar2list;
    l_add_stmts varchar2list;
    l_fetch_type varchar2(32767);
    c_date_type constant number := 12;
    c_timestamp_type constant number := 180;

    function repeatStmt(n in integer, template in varchar2, seperator in varchar2 := ‘‘, vals in varchar2list := null) return varchar2 is
        l_result varchar2(32767);
        l_stmt varchar2(32767);
    begin
        for i in 1..n loop
            l_stmt := template;
            if vals is not null then
                l_stmt := replace(template, ‘__val__‘, vals(i));
            end if;
            l_result := l_result || replace(l_stmt, ‘__$__‘, i);
            if i < n then
                l_result := l_result || seperator;
            end if;
        end loop;
        return l_result;
    end repeatStmt;
begin
    open rc_ for p_sql;
    n2 := p_no_of_cols;
    c_ := DBMS_SQL.to_cursor_number(rc_);
    DBMS_SQL.DESCRIBE_COLUMNS2(c_, col_count_, desc_tab_);
    col_num := desc_tab_.first;
    l_types := varchar2list();
    l_add_stmts := varchar2list();
    if col_num is not null then
        loop
            if desc_tab_(col_num).col_type = c_date_type or desc_tab_(col_num).col_type =c_timestamp_type then
                varchar2listAdd(l_types, ‘date‘);
                --to conform to jdbc date format
                varchar2listAdd(l_add_stmts, ‘varchar2ListAdd(l_str_list, to_char(a__$__, ‘‘yyyy-mm-dd hh:mi:ss‘‘));‘);
            else
                varchar2listAdd(l_types, ‘varchar2(32767)‘);
                varchar2listAdd(l_add_stmts, ‘varchar2ListAdd(l_str_list, a__$__);‘);
            end if;
            col_num:= desc_tab_.next(col_num);
            exit when (col_num is null);
        end loop;
    end if;

    --dbms_output.put_line(‘cursor count: ‘ || col_count_);
    n := col_count_;
    if n2 > n then
        n2 := n;
    end if;
    --dbms_output.put_line(‘number of columns: ‘ || n );
    --dbms_output.put_line(‘number of columns to fetch: ‘ || n2 );
    dbms_sql.close_cursor(c_);
    --if rc_%isopen then
    --    close rc_;
    --end if;
    code :=
    ‘ declare
        lc_rs sys_refcursor;
        l_sql varchar2(32767);
        l_str_list varchar2list;
        l_counter integer;
        l_any_list anydatalist; ‘ ||
        repeatStmt(n, ‘a__$__ __val__; ‘,  seperator => chr(10), vals => l_types) || ‘
      begin
        l_sql := :0;
        --dbms_output.put_line(l_sql);
        open lc_rs for l_sql;
        l_any_list := anydatalist();
        l_counter := 0;
        loop
            fetch lc_rs into ‘ || repeatStmt(n, ‘a__$__‘, ‘, ‘) || ‘;‘ || ‘
            exit when lc_rs%notfound;
            l_counter := l_counter + 1;
            l_str_list := varchar2List();‘ ||
            --repeatStmt(n2, ‘varchar2ListAdd(l_str_list, a__$__);‘, chr(10), vals => l_types) || ‘
            repeatStmt(n2, ‘__val__‘, chr(10), vals => l_add_stmts) || ‘
            anydataListAdd(l_any_list, anydata.convertCollection(l_str_list)); ‘ ||
            (case when p_return_multiple_row = false then
            ‘exit when l_counter = 1;‘
            end) || ‘
        end loop;
        if lc_rs%isopen then
            close lc_rs;
        end if;
        :1 := l_any_list;
      exception when others then
        dbms_output.put_line(‘‘ func_dynamic_fetch exec immediate exception: ‘‘ || sqlerrm);
        raise;
        if lc_rs%isopen then close lc_rs; end if;
      end;
    ‘ ;
    --dbms_output.put_line(code);
    execute immediate code using p_sql, out l_any_list;
    return l_any_list;
exception when others then
    if rc_%isopen then close rc_; end if;
    dbms_output.put_line(‘func_dynamic_fetch: exception: ‘ || sqlerrm);
    return anydatalist();
end;
 /
show errors;
时间: 2024-10-05 13:59:21

function dynamic fetch in Oracle的相关文章

使用Oracle的DBMS_SQL包执行动态SQL语句

使用Oracle的DBMS_SQL包执行动态SQL语句 引用自:http://blog.csdn.net/ggjjzhzz/archive/2005/10/17/507880.aspx 引用自:http://www.cnblogs.com/simonhaninmelbourne/archive/2013/01/23/2872438.html 在某些场合下,存储过程或触发器里的SQL语句需要动态生成.Oracle的DBMS_SQL包可以用来执行动态SQL语句.本文通过一个简单的例子来展示如何利用D

Oracle 11g Articles

发现一个比较有意思的网站,http://www.oracle-base.com/articles/11g/articles-11g.php Oracle 11g Articles Oracle Database 11g: New Features For Administrators OCP Exam Articles Oracle Database 11g Release 1: Miscellaneous Articles Oracle Database 11g Release 2: Misc

[独孤九剑]Oracle知识点梳理(七)数据库常用对象之Cursor

本系列链接导航: [独孤九剑]Oracle知识点梳理(一)表空间.用户 [独孤九剑]Oracle知识点梳理(二)数据库的连接 [独孤九剑]Oracle知识点梳理(三)导入.导出 [独孤九剑]Oracle知识点梳理(四)SQL语句之DML和DDL [独孤九剑]Oracle知识点梳理(五)数据库常用对象之Table.View [独孤九剑]Oracle知识点梳理(六)数据库常用对象之Procedure.function.Sequence [独孤九剑]Oracle知识点梳理(八)常见Exception

[独孤九剑]Oracle知识点梳理(四)SQL语句之DML和DDL

本系列链接导航: [独孤九剑]Oracle知识点梳理(一)表空间.用户 [独孤九剑]Oracle知识点梳理(二)数据库的连接 [独孤九剑]Oracle知识点梳理(三)导入.导出 [独孤九剑]Oracle知识点梳理(五)数据库常用对象之Table.View [独孤九剑]Oracle知识点梳理(六)数据库常用对象之Procedure.function.Sequence [独孤九剑]Oracle知识点梳理(七)数据库常用对象之Cursor [独孤九剑]Oracle知识点梳理(八)常见Exception

在 Oracle Linux 上使用 DTrace

作者:Richard Friedman 简要介绍适用于 Oracle Linux 的 DTrace 探测器和提供程序,以及与 Oracle Solaris 中 DTrace 探测器和提供程序的区别.还介绍了 DTrace 命令和脚本编写. 2013 年 6 月发布 DTrace 是一个全面的动态跟踪工具,最初是为 Oracle Solaris 操作系统开发的,现在 Oracle Linux 客户也可以使用.DTrace 旨在提供运营洞察力,允许用户实时动态调整和排除操作系统和应用程序故障.DTr

Linux Perf Probes for Oracle Tracing

Luca Canali on 21 Jan 2016 Topic: this post is about Linux perf and uprobes for tracing and profiling Oracle workloads for advanced troubleshooting. Context The recent progress and maturity of some of the Linux dynamic tracing tools has raised intere

oracle清除用户对象

在使用Oracle数据库的时候,经常会遇到需要把一个用户的所有对象重新导入的操作.这里介绍两种常用的方法,方便大家使用. 一.使用drop user cascade; 可以删除用户及所相关的所有对象,可以通过重新创建一个同名对象,然后使用imp 命令从dmp文件导入新的对象. 二.通过脚本把清空用户的所有对象,包含数据表.函数.存储过程等其他对象.采用这种方法,可以无需dba权限,在你需要完整导入一个用户数据的时候非常好用. 附:清除用户对象脚本 --PL/SQL Developer Test

[独孤九剑]Oracle知识点梳理(十)%type与%rowtype及常用函数

本系列链接导航: [独孤九剑]Oracle知识点梳理(一)表空间.用户 [独孤九剑]Oracle知识点梳理(二)数据库的连接 [独孤九剑]Oracle知识点梳理(三)导入.导出 [独孤九剑]Oracle知识点梳理(四)SQL语句之DML和DDL [独孤九剑]Oracle知识点梳理(五)数据库常用对象之Table.View [独孤九剑]Oracle知识点梳理(六)数据库常用对象之Procedure.function.Sequence [独孤九剑]Oracle知识点梳理(七)数据库常用对象之Curs

[独孤九剑]Oracle知识点梳理(八)常见Exception

本系列链接导航: [独孤九剑]Oracle知识点梳理(一)表空间.用户 [独孤九剑]Oracle知识点梳理(二)数据库的连接 [独孤九剑]Oracle知识点梳理(三)导入.导出 [独孤九剑]Oracle知识点梳理(四)SQL语句之DML和DDL [独孤九剑]Oracle知识点梳理(五)数据库常用对象之Table.View [独孤九剑]Oracle知识点梳理(六)数据库常用对象之Procedure.function.Sequence [独孤九剑]Oracle知识点梳理(七)数据库常用对象之Curs