警示:通過 wmsys.wm_concat 實現行列轉換
在網上流傳很多文章,描述了使用wmsys.wm_concat物件實現行列轉換的方法,這種方法不被Oracle所推薦,因為WMSYS使用者用於Workspace Manager,其函式物件可能因版本而不同,這種變化在11.2.0.3及10.2.0.5中體現出來。原本WM_CONCAT函式返回值為VARCHAR2變更為CLOB。這一變化導致了很多程式的異常。
該函式可以實現行列轉換:
SQL> select wmsys.wm_concat(username) from dba_users;
WMSYS.WM_CONCAT(USERNAME)--------------------------------------------------------------------------------SYS,SYSTEM,YANGTK,TEST,OUTLN,MGMT_VIEW,FLOWS_FILES,MDSYS,ORDSYS,EXFSYS,DBSNMP,WM
在11.2.0.3中,其返回值型別變更為CLOB:
SQL> desc wmsys.wm_concatFUNCTION wmsys.wm_concat RETURNS CLOBArgument Name Type In/Out Default?------------------------------ ----------------------- ------ --------P1 VARCHAR2 IN
Oracle建議使用者使用自定義函式來實現該功能,而不是使用WorkSpace的這個內部函式。
這個函式包含一個Type、Type Body、Function,可以參考Oracle的實現方式來實現這個函式。
請注意,在將資料庫從其他版本升級到10.2.0.5和11.2.0.3中時,必須注意到,這個函式的返回值型別變化。
例如如下一個系列的函式,可以幫助使用者構建自有的行列轉換函式:
SQL> create or replace TYPE en_concat_im2 AUTHID CURRENT_USER AS OBJECT3 (4 CURR_STR VARCHAR2(32767),5 STATIC FUNCTION ODCIAGGREGATEINITIALIZE(SCTX IN OUT en_concat_im) RETURN NUMBER,6 MEMBER FUNCTION ODCIAGGREGATEITERATE(SELF IN OUT en_concat_im,7 P1 IN VARCHAR2) RETURN NUMBER,8 MEMBER FUNCTION ODCIAGGREGATETERMINATE(SELF IN en_concat_im,9 RETURNVALUE OUT VARCHAR2,10 FLAGS IN NUMBER)11 RETURN NUMBER,12 MEMBER FUNCTION ODCIAGGREGATEMERGE(SELF IN OUT en_concat_im,13 SCTX2 IN en_concat_im) RETURN NUMBER14 );15 /
Type created.
SQL>SQL> create or replace TYPE BODY en_concat_im2 IS3 STATIC FUNCTION ODCIAGGREGATEINITIALIZE(SCTX IN OUT en_concat_im)4 RETURN NUMBER5 IS6 BEGIN7 SCTX := en_concat_im(NULL) ;8 RETURN ODCICONST.SUCCESS;9 END;10 MEMBER FUNCTION ODCIAGGREGATEITERATE(SELF IN OUT en_concat_im,11 P1 IN VARCHAR2)12 RETURN NUMBER13 IS14 BEGIN15 IF(CURR_STR IS NOT NULL) THEN16 CURR_STR := CURR_STR || ';' || P1;17 ELSE18 CURR_STR := P1;19 END IF;20 RETURN ODCICONST.SUCCESS;21 END;22 MEMBER FUNCTION ODCIAGGREGATETERMINATE(SELF IN en_concat_im,23 RETURNVALUE OUT VARCHAR2,24 FLAGS IN NUMBER)25 RETURN NUMBER26 IS27 BEGIN28 RETURNVALUE := CURR_STR ;29 RETURN ODCICONST.SUCCESS;30 END;31 MEMBER FUNCTION ODCIAGGREGATEMERGE(SELF IN OUT en_concat_im,32 SCTX2 IN en_concat_im)33 RETURN NUMBER34 IS35 BEGIN36 IF(SCTX2.CURR_STR IS NOT NULL) THEN37 SELF.CURR_STR := SELF.CURR_STR || ';' || SCTX2.CURR_STR ;38 END IF;39 RETURN ODCICONST.SUCCESS;40 END;41 END;42 /
Type body created.
SQL> create or replace FUNCTION en_concat(P1 VARCHAR2) RETURN VARCHAR2 AGGREGATE USING en_concat_im ;2 /
Function created.
SQL> select en_concat(username) from dba_users;
EN_CONCAT(USERNAME)--------------------------------------------------------------------------------SYS;SYSTEM;YANGTK;TEST;OUTLN;MGMT_VIEW;FLOWS_FILES;MDSYS;ORDSYS;EXFSYS;DBSNMP;WMSYS;APPQOSSYS;APEX_030200;OWBSYS_AUDIT;ORDDATA;CTXSYS;ANONYMOUS;SYSMAN;XDB;ORDPLUGINS;OWBSYS;SI_INFORMTN_SCHEMA;OLAPSYS;ORACLE_OCM;XS$NULL;MDDATA;DIP;APEX_PUBLIC_USER;SPATIAL_CSW_ADMIN_USR;SPATIAL_WFS_ADMIN_USR
以上改變還存在一個潛在的效能風險,那就是使用CLOB時會用到臨時段,在高壓力系統下,臨時檔案的大量佔用會導致臨時表空間的迅速增長。使用10046事件跟蹤,可以清晰的看到這些變化,以下是使用10046事件跟蹤兩個查詢:
SQL> alter session set events '10046 trace name context forever,level 12';
Session altered.
SQL> select wmsys.wm_concat(username) from dba_users;
WMSYS.WM_CONCAT(USERNAME)--------------------------------------------------------------------------------SYS,SYSTEM,YANGTK,TEST,OUTLN,MGMT_VIEW,FLOWS_FILES,MDSYS,ORDSYS,EXFSYS,DBSNMP,WM
SQL> select en_concat(username) from dba_users;
EN_CONCAT(USERNAME)--------------------------------------------------------------------------------SYS;SYSTEM;YANGTK;TEST;OUTLN;MGMT_VIEW;FLOWS_FILES;MDSYS;ORDSYS;EXFSYS;DBSNMP;WMSYS;APPQOSSYS;APEX_030200;OWBSYS_AUDIT;ORDDATA;CTXSYS;ANONYMOUS;SYSMAN;XDB;ORDPLUGINS;OWBSYS;SI_INFORMTN_SCHEMA;OLAPSYS;ORACLE_OCM;XS$NULL;MDDATA;DIP;APEX_PUBLIC_USER;SPATIAL_CSW_ADMIN_USR;SPATIAL_WFS_ADMIN_USR
查詢日誌輸出如下,其中Disk file operations I/O 操作了檔案201,即臨時檔案:
=====================PARSING IN CURSOR #139839047786312 len=47 dep=0 uid=0 oct=3 lid=0 tim=1346138299723909 hv=2250098298 ad='b855e660' sqlid='75n6afa31vjmu'select wmsys.wm_concat(username) from dba_usersEND OF STMTPARSE #139839047786312:c=12999,e=12924,p=0,cr=107,cu=0,mis=1,r=0,dep=0,og=1,plh=4128086143,tim=1346138299723908EXEC #139839047786312:c=0,e=68,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=4128086143,tim=1346138299724042WAIT #139839047786312: nam='SQL*Net message to client' ela= 1 driver id=1650815232 #bytes=1 p3=0 obj#=539 tim=1346138299724094WAIT #139839047786312: nam='SQL*Net message from client' ela= 126 driver id=1650815232 #bytes=1 p3=0 obj#=539 tim=1346138299724260WAIT #139839047786312: nam='Disk file operations I/O' ela= 41 FileOperation=2 fileno=201 filetype=2 obj#=539 tim=1346138299726980WAIT #139839047786312: nam='SQL*Net message to client' ela= 1 driver id=1650815232 #bytes=1 p3=0 obj#=539 tim=1346138299727257FETCH #139839047786312:c=2999,e=3001,p=0,cr=28,cu=17,mis=0,r=1,dep=0,og=1,plh=4128086143,tim=1346138299727281STAT #139839047786312 id=1 cnt=1 pid=0 pos=1 obj=0 op='SORT AGGREGATE (cr=28 pr=0 pw=0 time=2996 us)'STAT #139839047786312 id=2 cnt=31 pid=1 pos=1 obj=0 op='HASH JOIN (cr=28 pr=0 pw=0 time=1903 us cost=22 size=1764 card=21)'STAT #139839047786312 id=3 cnt=31 pid=2 pos=1 obj=0 op='HASH JOIN (cr=26 pr=0 pw=0 time=1815 us cost=20 size=1701 card=21)'STAT #139839047786312 id=4 cnt=31 pid=3 pos=1 obj=0 op='HASH JOIN (cr=20 pr=0 pw=0 time=1622 us cost=16 size=1638 card=21)'STAT #139839047786312 id=5 cnt=31 pid=4 pos=1 obj=0 op='HASH JOIN OUTER (cr=14 pr=0 pw=0 time=1442 us cost=13 size=1575 card=21)'STAT #139839047786312 id=6 cnt=31 pid=5 pos=1 obj=0 op='HASH JOIN (cr=12 pr=0 pw=0 time=810 us cost=10 size=966 card=21)'STAT #139839047786312 id=7 cnt=31 pid=6 pos=1 obj=0 op='HASH JOIN (cr=10 pr=0 pw=0 time=486 us cost=8 size=924 card=21)'STAT #139839047786312 id=8 cnt=1 pid=7 pos=1 obj=0 op='MERGE JOIN CARTESIAN (cr=4 pr=0 pw=0 time=83 us cost=4 size=16 card=1)'STAT #139839047786312 id=9 cnt=1 pid=8 pos=1 obj=281 op='TABLE ACCESS FULL PROFILE$ (cr=2 pr=0 pw=0 time=40 us cost=2 size=8 card=1)'STAT #139839047786312 id=10 cnt=1 pid=8 pos=2 obj=0 op='BUFFER SORT (cr=2 pr=0 pw=0 time=32 us cost=2 size=8 card=1)'STAT #139839047786312 id=11 cnt=1 pid=10 pos=1 obj=281 op='TABLE ACCESS FULL PROFILE$ (cr=2 pr=0 pw=0 time=15 us cost=2 size=8 card=1)'STAT #139839047786312 id=12 cnt=31 pid=7 pos=2 obj=22 op='TABLE ACCESS FULL USER$ (cr=6 pr=0 pw=0 time=41 us cost=3 size=784 card=28)'STAT #139839047786312 id=13 cnt=1 pid=6 pos=2 obj=282 op='TABLE ACCESS FULL PROFNAME$ (cr=2 pr=0 pw=0 time=11 us cost=2 size=2 card=1)'STAT #139839047786312 id=14 cnt=2 pid=5 pos=2 obj=298 op='TABLE ACCESS FULL RESOURCE_GROUP_MAPPING$ (cr=2 pr=0 pw=0 time=16 us cost=2 size=29 card=1)'STAT #139839047786312 id=15 cnt=5 pid=4 pos=2 obj=16 op='TABLE ACCESS FULL TS$ (cr=6 pr=0 pw=0 time=80 us cost=3 size=15 card=5)'STAT #139839047786312 id=16 cnt=5 pid=3 pos=2 obj=16 op='TABLE ACCESS FULL TS$ (cr=6 pr=0 pw=0 time=10 us cost=3 size=15 card=5)'STAT #139839047786312 id=17 cnt=9 pid=2 pos=2 obj=293 op='TABLE ACCESS FULL USER_ASTATUS_MAP (cr=2 pr=0 pw=0 time=16 us cost=2 size=27 card=9)'WAIT #139839047786312: nam='SQL*Net message from client' ela= 123 driver id=1650815232 #bytes=1 p3=0 obj#=539 tim=1346138299727940WAIT #0: nam='SQL*Net message to client' ela= 0 driver id=1650815232 #bytes=1 p3=0 obj#=539 tim=1346138299727989LOBREAD: c=0,e=36,p=0,cr=2,cu=0,tim=1346138299728000WAIT #0: nam='SQL*Net message from client' ela= 156 driver id=1650815232 #bytes=1 p3=0 obj#=539 tim=1346138299728176LOBTMPFRE: c=0,e=44,p=0,cr=0,cu=5,tim=1346138299728297WAIT #0: nam='SQL*Net message to client' ela= 1 driver id=1650815232 #bytes=1 p3=0 obj#=539 tim=1346138299728328WAIT #0: nam='SQL*Net message from client' ela= 29 driver id=1650815232 #bytes=1 p3=0 obj#=539 tim=1346138299728367FETCH #139839047786312:c=0,e=2,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=0,plh=4128086143,tim=1346138299728385WAIT #139839047786312: nam='SQL*Net message to client' ela= 0 driver id=1650815232 #bytes=1 p3=0 obj#=539 tim=1346138299728399
*** 2012-08-28 15:18:25.570WAIT #139839047786312: nam='SQL*Net message from client' ela= 5842346 driver id=1650815232 #bytes=1 p3=0 obj#=539 tim=1346138305570755CLOSE #139839047786312:c=0,e=11,dep=0,type=0,tim=1346138305570850=====================PARSING IN CURSOR #139839047799848 len=37 dep=1 uid=0 oct=3 lid=0 tim=1346138305571205 hv=1398610540 ad='c183e438' sqlid='grwydz59pu6mc'select text from view$ where rowid=:1END OF STMTPARSE #139839047799848:c=0,e=24,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,plh=3684871272,tim=1346138305571204BINDS #139839047799848:Bind#0oacdty=11 mxl=16(16) mxlc=00 mal=00 scl=00 pre=00oacflg=18 fl2=0001 frm=00 csi=00 siz=16 off=0kxsbbbfp=7f2ed0d08410 bln=16 avl=16 flg=05value=00002294.0002.0001EXEC #139839047799848:c=1000,e=56,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,plh=3684871272,tim=1346138305571319FETCH #139839047799848:c=0,e=19,p=0,cr=2,cu=0,mis=0,r=1,dep=1,og=4,plh=3684871272,tim=1346138305571351STAT #139839047799848 id=1 cnt=1 pid=0 pos=1 obj=69 op='TABLE ACCESS BY USER ROWID VIEW$ (cr=1 pr=0 pw=0 time=13 us cost=1 size=15 card=1)'CLOSE #139839047799848:c=0,e=30,dep=1,type=0,tim=1346138305571394=====================PARSING IN CURSOR #139839047786312 len=41 dep=0 uid=0 oct=3 lid=0 tim=1346138305582448 hv=4228787766 ad='b8517a08' sqlid='75b6jnvy0wbjq'select en_concat(username) from dba_usersEND OF STMTPARSE #139839047786312:c=10999,e=11557,p=0,cr=98,cu=0,mis=1,r=0,dep=0,og=1,plh=4128086143,tim=1346138305582447EXEC #139839047786312:c=0,e=49,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=4128086143,tim=1346138305582560WAIT #139839047786312: nam='SQL*Net message to client' ela= 2 driver id=1650815232 #bytes=1 p3=0 obj#=539 tim=1346138305582592FETCH #139839047786312:c=2000,e=2480,p=0,cr=28,cu=0,mis=0,r=1,dep=0,og=1,plh=4128086143,tim=1346138305585093STAT #139839047786312 id=1 cnt=1 pid=0 pos=1 obj=0 op='SORT AGGREGATE (cr=28 pr=0 pw=0 time=2493 us)'STAT #139839047786312 id=2 cnt=31 pid=1 pos=1 obj=0 op='HASH JOIN (cr=28 pr=0 pw=0 time=1979 us cost=22 size=1764 card=21)'STAT #139839047786312 id=3 cnt=31 pid=2 pos=1 obj=0 op='HASH JOIN (cr=26 pr=0 pw=0 time=1842 us cost=20 size=1701 card=21)'STAT #139839047786312 id=4 cnt=31 pid=3 pos=1 obj=0 op='HASH JOIN (cr=20 pr=0 pw=0 time=1669 us cost=16 size=1638 card=21)'STAT #139839047786312 id=5 cnt=31 pid=4 pos=1 obj=0 op='HASH JOIN OUTER (cr=14 pr=0 pw=0 time=1517 us cost=13 size=1575 card=21)'STAT #139839047786312 id=6 cnt=31 pid=5 pos=1 obj=0 op='HASH JOIN (cr=12 pr=0 pw=0 time=839 us cost=10 size=966 card=21)'STAT #139839047786312 id=7 cnt=31 pid=6 pos=1 obj=0 op='HASH JOIN (cr=10 pr=0 pw=0 time=490 us cost=8 size=924 card=21)'STAT #139839047786312 id=8 cnt=1 pid=7 pos=1 obj=0 op='MERGE JOIN CARTESIAN (cr=4 pr=0 pw=0 time=110 us cost=4 size=16 card=1)'STAT #139839047786312 id=9 cnt=1 pid=8 pos=1 obj=281 op='TABLE ACCESS FULL PROFILE$ (cr=2 pr=0 pw=0 time=69 us cost=2 size=8 card=1)'STAT #139839047786312 id=10 cnt=1 pid=8 pos=2 obj=0 op='BUFFER SORT (cr=2 pr=0 pw=0 time=35 us cost=2 size=8 card=1)'STAT #139839047786312 id=11 cnt=1 pid=10 pos=1 obj=281 op='TABLE ACCESS FULL PROFILE$ (cr=2 pr=0 pw=0 time=17 us cost=2 size=8 card=1)'STAT #139839047786312 id=12 cnt=31 pid=7 pos=2 obj=22 op='TABLE ACCESS FULL USER$ (cr=6 pr=0 pw=0 time=40 us cost=3 size=784 card=28)'STAT #139839047786312 id=13 cnt=1 pid=6 pos=2 obj=282 op='TABLE ACCESS FULL PROFNAME$ (cr=2 pr=0 pw=0 time=9 us cost=2 size=2 card=1)'STAT #139839047786312 id=14 cnt=2 pid=5 pos=2 obj=298 op='TABLE ACCESS FULL RESOURCE_GROUP_MAPPING$ (cr=2 pr=0 pw=0 time=14 us cost=2 size=29 card=1)'STAT #139839047786312 id=15 cnt=5 pid=4 pos=2 obj=16 op='TABLE ACCESS FULL TS$ (cr=6 pr=0 pw=0 time=28 us cost=3 size=15 card=5)'STAT #139839047786312 id=16 cnt=5 pid=3 pos=2 obj=16 op='TABLE ACCESS FULL TS$ (cr=6 pr=0 pw=0 time=13 us cost=3 size=15 card=5)'STAT #139839047786312 id=17 cnt=9 pid=2 pos=2 obj=293 op='TABLE ACCESS FULL USER_ASTATUS_MAP (cr=2 pr=0 pw=0 time=8 us cost=2 size=27 card=9)'WAIT #139839047786312: nam='SQL*Net message from client' ela= 193 driver id=1650815232 #bytes=1 p3=0 obj#=539 tim=1346138305585818FETCH #139839047786312:c=0,e=1,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=0,plh=4128086143,tim=1346138305585841WAIT #139839047786312: nam='SQL*Net message to client' ela= 1 driver id=1650815232 #bytes=1 p3=0 obj#=539 tim=1346138305585855
*** 2012-08-28 15:18:34.648WAIT #139839047786312: nam='SQL*Net message from client' ela= 9062490 driver id=1650815232 #bytes=1 p3=0 obj#=539 tim=1346138314648354CLOSE #139839047786312:c=0,e=10,dep=0,type=0,tim=1346138314648443=====================
以上問題在版本升級時需要注意。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29439655/viewspace-1463075/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- wmsys.wm_concat 實現行列轉換問題
- wmsys.wm_concat、sys_connect_by_path、自定義函式實現行列轉換函式
- 【轉】Oracle: wmsys.wm_concat、sys_connect_by_path、自定義函式實現行列轉換Oracle函式
- Oracle10g的行列轉換 wmsys.wm_concatOracle
- pivot、unpivot實現oracle行列轉換Oracle
- sql 實現表的行列轉換SQL
- Spark實現行列轉換pivot和unpivotSpark
- WORD及EXCEL行列轉換實現方法收藏(轉)Excel
- SQL Server 實現行列(縱橫表)轉換SQLServer
- 用ORACLE分析函式實現行列轉換Oracle函式
- 試驗Oracle中實現行列轉換的方法(轉)Oracle
- 行列轉換
- 使用vue實現行列轉換的一種方法。Vue
- 在Word中實現表格的行列互換 (轉)
- Kettle行列轉換
- 偽行列轉換!
- 行列轉換sqlSQL
- 用abap實現內表的行列轉換-原始碼2 (轉)原始碼
- Oracle--SQL行列轉換實戰OracleSQL
- 行列轉換 交叉表 (轉)
- 通過JDOM實現XML與String的相互轉換XML
- Oracle-行列轉換Oracle
- MySQL行列轉換拼接MySql
- 行列轉換之大全~~~
- sql server 行列轉換SQLServer
- 報表如何實現行列互換效果?
- oracle行列轉換-多行轉換成字串Oracle字串
- 行列轉換,列行轉換統計
- 在SQL Server 2005中實現表的行列轉換SQLServer
- 教程:如何通過DLA實現資料檔案格式轉換
- oracle行列轉換-行轉列Oracle
- oracle行列轉換-列轉行Oracle
- Restcloud ETl實踐之資料行列轉換RESTCloud
- 幾個行列轉換的實用小例子
- mysql行列轉換詳解MySql
- sql server行列轉換案例SQLServer
- Oracle 行列轉換 經典Oracle
- Oracle 行列轉換總結Oracle