PLSQL中怎樣獲取未知結(jié)構(gòu)的動(dòng)態(tài)游標(biāo)的字段名
對(duì)于使用過(guò) ORACLE PLSQL 中的動(dòng)態(tài)游標(biāo)的人來(lái)說(shuō),我相信有不少人都會(huì)有這樣的想法:如果對(duì)于任意一個(gè)給定的未知結(jié)構(gòu)的游標(biāo)(REF CURSOR),我們都能夠在PLSQL中獲取它的所有字段的名稱,那該多好啊!不知道你是否有這樣的想法,反正我早就有這樣的想法了,也百度了多次,但結(jié)果不盡人意。曾經(jīng)一度以為,這是不可能的。但是PLSQL Developer中的test 窗口中,可以打開(kāi)任意游標(biāo)并得到字段名及值。很顯然,還是有辦法得到未知結(jié)構(gòu)的動(dòng)態(tài)游標(biāo)的字段名的,只是我不知道方法而已。
今天早上心血來(lái)潮,又想到這個(gè)事情,于是google了一下(用英文查詢:how to get column names from oracle cursor),發(fā)現(xiàn)還真有辦法獲取未知結(jié)構(gòu)的動(dòng)態(tài)游標(biāo)!看來(lái)在這方面百度還是太弱啊!技術(shù)問(wèn)題還是得問(wèn)google。
整理之后,結(jié)論如下:
1、如果給的是一個(gè)查詢SQL文本,那么事情很容易(對(duì)于9i及以上版本),只要使用dbms_sql.open_cursor打開(kāi)游標(biāo),再使用dbms_sql.describe_columns即可得到游標(biāo)的所有字段名稱及類型等數(shù)據(jù),存儲(chǔ)在一個(gè)集合類型變量中(具體請(qǐng)看dbms_sql.desc_tab)。請(qǐng)參考如下PLSQL代碼:
DECLARE
l_curidINTEGER; l_cntNUMBER;
l_desctabdbms_sql.desc_tab; l_sqltextVARCHAR2(2000); BEGIN
l_sqltext := 'select owner,object_type,object_name from dba_objects
where rownum<= 10';--可以是任意有效的查詢sql文本 l_curid := dbms_sql.open_cursor();
dbms_sql.parse(l_curid, l_sqltext, dbms_sql.native); dbms_sql.describe_columns(l_curid, l_cnt, l_descTab);
FOR i IN1 ..l_desctab.count LOOP
dbms_output.put(lpad(l_desctab(i).col_name, 20)); ENDLOOP;
dbms_output.new_line;
dbms_sql.close_cursor(l_curId); END;
運(yùn)行結(jié)果如下:
OWNER OBJECT_TYPE OBJECT_NAME
注意,必須使用 DBMS_SQL.OPEN_CURSOR 打開(kāi)游標(biāo),否則,就不是這種處理方法了。
2、如果給的是一個(gè)REF CURSOR類型變量,而不知道SQL文本,該怎么辦呢?這里分兩種情況:
1) 如果數(shù)據(jù)庫(kù)版本是11g及以上,同樣很容易:使用dbms_sql.to_cursor_number(cursor)
得到游標(biāo)的ID,再使用dbms_sql.describe_columns即可得到游標(biāo)字段名稱。參考如下代碼:
DECLARE
TYPEref_cursorISREFCURSOR; l_cursorref_cursor; l_curidNUMBER; l_col_cntNUMBER;
l_desc_tab DBMS_SQL.DESC_TAB; BEGIN
OPENl_cursorFOR'select owner,object_type,object_name from dba_objects where rownum<= 10';
l_curid := DBMS_SQL.to_cursor_number(l_cursor);
DBMS_SQL.DESCRIBE_COLUMNS(l_curid, l_col_cnt, l_desc_tab);
FOR i_ IN1 ..l_col_cnt LOOP
DBMS_OUTPUT.PUT_LINE(l_desc_tab(i).col_name); ENDLOOP;
DBMS_SQL.CLOSE_CURSOR(l_cursor); END;
2) 如果數(shù)據(jù)庫(kù)版本低于11g,則PLSQL中僅有如下方法可以獲取字段名稱及字段值:
DECLARE
l_cursorSYS_REFCURSOR; iNUMBER := 0;
CURSORget_columnsIS
SELECT t2.column_value.getrootelement() NAME, EXTRACTVALUE(t2.column_value, 'node()') VALUE
FROM (SELECT * FROMTABLE(XMLSEQUENCE(l_cursor))) t1,
TABLE(XMLSEQUENCE(EXTRACT(t1.column_value, '/ROW/node()'))) t2; BEGIN
OPENl_cursorFOR'select owner,object_type,object_name from dba_objects where rownum<= 10';
FOR rec_ INget_columns
LOOP
i := i + 1;
DBMS_OUTPUT.put_line(i || ':' || rec_.name || ': ' || rec_.VALUE); ENDLOOP;
CLOSEl_cursor; END;
用這種方法,可以得到動(dòng)態(tài)游標(biāo)的所有數(shù)據(jù),包括字段名稱和字段值。但這種方法會(huì)遍歷游標(biāo),即游標(biāo)已經(jīng)走到底了,不能再次使用了。而使用dbms_sql.describe_columns不會(huì)對(duì)游標(biāo)的光標(biāo)位置產(chǎn)生任何影響。兩者優(yōu)劣一目了然。
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)
點(diǎn)擊舉報(bào)。