• Dynamic Cursor in plsql (2)


    获取cursor行数:

    当游标被打开后,%ROWCOUNT归零。第一次提取之前,cursor_name%ROWCOUNT返回0。此后,它返回的fetch到的行数。完成一次fetch操作后,count+1。

    获取cursor 列数:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    --方法一:
    CREATE OR REPLACE FUNCTION count_sql( p_sql IN CLOB )
    RETURN INTEGER
    AS
            lv_cursor_id    INTEGER;
            lv_columns      DBMS_SQL.DESC_TAB;
            lv_column_count INTEGER;
    BEGIN
            -- Open Cursor
            lv_cursor_id := DBMS_SQL.OPEN_CURSOR;
             
            -- Parse Cursor
            DBMS_SQL.PARSE
            ( c             => lv_cursor_id
            , statement     => p_sql
            , language_flag => DBMS_SQL.NATIVE
            );
             
            -- Describe Columns
            DBMS_SQL.DESCRIBE_COLUMNS
            ( c       => lv_cursor_id   
            , col_cnt => lv_column_count
            , desc_t  => lv_columns
            );
             
            -- Close Cursor
            DBMS_SQL.CLOSE_CURSOR(lv_cursor_id);
             
            RETURN lv_column_count;
    END count_sql;
    /
     
    SELECT count_sql('SELECT dummy, dummy, dummy, ''Y'' FROM DUAL') FROM DUAL;
     
    COUNT_SQL('SELECTDUMMY,DUMMY,DUMMY,''Y''FROMDUAL')
    --------------------------------------------------
                                                     4
    ================================================================
    --方法二:
     
    SQL> select column_value cnt from xmltable('count(distinct-values(for $i in ROW/* return name($i)))'
      passing dbms_xmlgen.getxmltype('select ename, sal, hiredate, deptno from emp').extract('ROWSET/ROW')
    )
     
    CNT 
    -----
    4   
    1 row selected.
    SQL> select column_value cnt from xmltable('count(distinct-values(for $i in ROW/* return name($i)))'
      passing dbms_xmlgen.getxmltype('select sal, job, deptno from emp').extract('ROWSET/ROW')
    )
     
    CNT 
    -----
    3   
    1 row selected.

    动态执行sql语句的函数:

    func_dynamic_fetch(l_sql);----l_sql 为sql语句

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    CREATE OR REPLACE TYPE AnydataList FORCE IS VARRAY (2147483647) OF ANYDATA  ;
    /
    CREATE OR REPLACE TYPE Varchar2List FORCE IS VARRAY (2147483647) OF VARCHAR2 (32767) ;
    /
    create or replace function func_dynamic_fetch
    (   p_sql in varchar2,
        p_no_of_cols integer := 1, 
        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;
         
        n := col_count_;
        if n2 > n then
            n2 := n;
        end if;
        dbms_sql.close_cursor(c_);
        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, '__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;
        ' ;
        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;
  • 相关阅读:
    python_函数_文件
    Day_2_Python_str_list_dict的使用
    Day_1_Python_循环和格式化
    influxdb2.0版本部署+自启
    格式化Java内存工具JOL输出
    卷心菜的屯币日记
    influxDB时序数据库2.0FLUX查询语法使用记录
    两种转换2021-01-01T00:00:00Z为2021-01-01 00:00:00时间格式的方式(UTC时间转为yyyy-MM-dd HH:mm:ss)
    ThreadLocal的用处
    CentOS7使用ISO镜像文件作为离线Yum源
  • 原文地址:https://www.cnblogs.com/Jeffrey-xu/p/5057700.html
Copyright © 2020-2023  润新知