获取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;
|