這兩天在項目中遇到了一個問題,就是系統中使用了wmsys.wm_concat引發的相關問題,PM也提議不要使用,原因有下:
1.該函數不是oracle公開的系統函數,它的用戶是wmsys,而不是sys或者system,oracle很有可能在版本升級或者補丁的時候取消或者修改這個函數甚至用戶,這種變化oracle是不會公開的。所有可能會由於這個變化而導致異常。
2.大量使用這個函數也會導致臨時表空間爆滿,這是因爲在10.2.0.5中,使用wmsys.wm_concat返回的結果格式是CLOB,CLOB佔用的臨時表空間只有在連接釋放後纔會釋放,部分通過連接池連接數據庫的長連接很有可能導致CLOB佔用臨時表空間不斷累積增大,會導致臨時表空間爆滿的故障
3.如果是在程序中大量使用這個函數的話會引起enq:TT的鎖,可能會導致某些對象被鎖。
解決辦法:
官方文檔給了建議,可以參考該函數自己建立一個函數實現相同的行列轉換功能。
然後我上網找了一些資料,http://www.eygle.com/archives/2012/10/wmsys_wm_concat.html
確實可以實現跟wmsys.wm_concat一樣的功能,下面是這篇文章的實現
create or replace TYPE en_concat_im
create or replace TYPE BODY en_concat_im
然後運行測試:select en_concat(username) from dba_users; ok可以實現行列轉換。具體的性能分析可以瀏覽該網址的文章
但是我在運行的時候出了個問題,就是查詢的表數據量比較大的時候會報:Oracle ORA-06502: PL/SQL: 數字或值錯誤 : 字符串緩衝區太小這個錯誤
我當時不明白什麼原因,後面百度了一下這個原因,看到了一篇文章:http://bbs.csdn.net/topics/360059765
樓主的問題:
使用wmsys.wm_concat多列合成一列遇到問題
ORA-22813: 操作數值超出系統的限制
往下看了之後對比了一下這個問題的解決辦法,原理跟上面一樣,也是自定義type來實現,但是有一個不同點的就是,上面的實現我標註的地方,返回的是varchar2類型的
在看看這篇文章裏面的實現:
CREATE
OR
REPLACE
TYPE zh_concat_im
AUTHID
CURRENT_USER
AS
OBJECT
(
CURR_STR clob,
STATIC
FUNCTION
ODCIAGGREGATEINITIALIZE(SCTX
IN
OUT
zh_concat_im)
RETURN
NUMBER,
MEMBER
FUNCTION
ODCIAGGREGATEITERATE(SELF
IN
OUT
zh_concat_im,
P1
IN
VARCHAR2)
RETURN
NUMBER,
MEMBER
FUNCTION
ODCIAGGREGATETERMINATE(SELF
IN
zh_concat_im,
RETURNVALUE
OUT
clob,
FLAGS
IN
NUMBER)
RETURN
NUMBER,
MEMBER
FUNCTION
ODCIAGGREGATEMERGE(SELF
IN
OUT
zh_concat_im,
SCTX2
IN
zh_concat_im)
RETURN
NUMBER
);
CREATE
OR
REPLACE
TYPE BODY zh_concat_im
IS
STATIC
FUNCTION
ODCIAGGREGATEINITIALIZE(SCTX
IN
OUT
zh_concat_im)
RETURN
NUMBER
IS
BEGIN
SCTX := zh_concat_im(
NULL
) ;
RETURN
ODCICONST.SUCCESS;
END
;
MEMBER
FUNCTION
ODCIAGGREGATEITERATE(SELF
IN
OUT
zh_concat_im,
P1
IN
VARCHAR2)
RETURN
NUMBER
IS
BEGIN
IF(CURR_STR
IS
NOT
NULL
)
THEN
CURR_STR := CURR_STR ||
','
|| P1;
ELSE
CURR_STR := P1;
END
IF;
RETURN
ODCICONST.SUCCESS;
END
;
MEMBER
FUNCTION
ODCIAGGREGATETERMINATE(SELF
IN
zh_concat_im,
RETURNVALUE
OUT
clob,
FLAGS
IN
NUMBER)
RETURN
NUMBER
IS
BEGIN
RETURNVALUE := CURR_STR ;
RETURN
ODCICONST.SUCCESS;
END
;
MEMBER
FUNCTION
ODCIAGGREGATEMERGE(SELF
IN
OUT
zh_concat_im,
SCTX2
IN
zh_concat_im)
RETURN
NUMBER
IS
BEGIN
IF(SCTX2.CURR_STR
IS
NOT
NULL
)
THEN
SELF.CURR_STR := SELF.CURR_STR ||
','
|| SCTX2.CURR_STR ;
END
IF;
RETURN
ODCICONST.SUCCESS;
END
;
END
;
create
or
replace
FUNCTION
zh_concat(P1 VARCHAR2)
RETURN
clob AGGREGATE USING zh_concat_im ;
這個定義的的clob類型,所有這個函數可以實現,沒有出現了Oracle ORA-06502:這個錯誤,頓時恍然啊。
至於clob這個類型跟varchar2各位就查資料看看了,但是目前我還是有點不明白,這樣實現也是用clob這個類型,會不會也會臨時表空間增大,目前沒有測試過。
以上就是這兩天查資料看到的這些,有錯的地方希望指出來了;我oracle也不是很熟哈!!!如果哪位大神能更好的說明的那就更好了。