日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

重写Oracle的wm_concat函数,自定义分隔符、排序

發布時間:2024/9/20 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 重写Oracle的wm_concat函数,自定义分隔符、排序 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

oracle中,wm_concat函數是一個聚合函數,和mysql中的group_concat函數類似,不過group_concat函數比較強大,可以定義分隔符和排序,當然所謂強大是相對的,這里假使我們不知道oracle中的over函數,也不知道listagg函數。

? ? ? ?我們先來看看wm_concat函數能實現什么功能,通俗點==>列傳行,如果不明白,請看下面截圖(可以看到分隔符默認為','順序也是雜亂的)

? ? ? ?

? ? ? ??

? ? ? ?所以,接下來,我們開始重寫wm_concat函數(需要注意和需要說明的地方放在代碼注釋中...)

(1) 因為需要進行排序,首先自定義一個可變數組

1 2 -- 定義可變數組,字符串類型,長度32767,存放列值 CREATE?OR?REPLACE?TYPE WYARRAY?as?TABLE?OF?VARCHAR(32767) ;

(2)自定義排序函數、分隔符函數

1 2 3 4 5 6 7 8 9 10 11 12 -- 定義分隔符函數 create?or?replace?function?delimiter(colValue??in?varchar2, ?????????????????????????????????????delimiter?in?varchar2)?return?varchar2?is ??rtnValue varchar2(32767); begin ??rtnValue := colValue ||?' delimiter=>'?|| delimiter ||?'; '; ??return?rtnValue; end?delimiter;
1 2 3 4 5 6 7 8 9 10 11 12 -- 定義排序函數 create?or?replace?function?orderby(colValue?in?varchar2, ???????????????????????????????????orderby??in?varchar2)?return?varchar2?is ??rtnValue varchar2(32767); begin ??rtnValue := colValue ||?' orderby=>'?||?LOWER(orderby) ||?'; '; ??return?rtnValue; end?orderby;

(3) 重定義oracle接口函數、以及接口函數的實現體(實現分隔符和排序的主要代碼)

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 -- 使用當前用戶權限(使用authid current_user,定義type為用戶當前用戶的權限,舉個例子:比如A用戶他可以建立表,但是A用戶在存儲過程中如果建立表可能會提示權限不夠,所以需要用authid current_user進行約束) create?or?replace?type wy_wm_concat authid?current_user?as?object ( --拼接字符串,存放中間值,當然也可以定義為clob,clob會使用臨時段,導致臨時表空間迅速增大; --查看wmsys下的function可以發現Oracle10g到oracle11g自帶的wm_concat函數的返回類型從clob變成varchar2 ??currStr VARCHAR2(32767), --分割字符串 ??delimiter VARCHAR2(64), --排序字符串(asc、desc) ??orderby VARCHAR2(64), -- 定義字符串數組 ??strArray WYARRAY, -- 初始化接口函數 ??STATIC?FUNCTION?ODCIAGGREGATEINITIALIZE(init?IN?OUT?wy_wm_concat) ????RETURN?NUMBER, -- 迭代接口函數 ??MEMBER?FUNCTION?ODCIAGGREGATEITERATE(self?????IN?OUT?wy_wm_concat, ???????????????????????????????????????colValue?IN?VARCHAR2)?RETURN?NUMBER, -- 并行時字符串合并的接口函數 ??MEMBER?FUNCTION?ODCIAGGREGATEMERGE(self?IN?OUT?wy_wm_concat, ?????????????????????????????????????next?wy_wm_concat)?RETURN?NUMBER, -- oracle終止接口函數 ??MEMBER?FUNCTION?ODCIAGGREGATETERMINATE(self????????IN?wy_wm_concat, ?????????????????????????????????????????returnValue?OUT?VARCHAR2, ?????????????????????????????????????????flags???????IN?NUMBER) ????RETURN?NUMBER )
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 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 create?or?replace?type body wy_wm_concat?is??--定義函數的body ??--初始化函數 ??STATIC?FUNCTION?ODCIAGGREGATEINITIALIZE(init?IN?OUT?wy_wm_concat) ????RETURN?NUMBER?is ??begin ????init := wy_wm_concat('',?',',?'asc', WYARRAY()); ????return?ODCICONST.Success; ??END; ??-- 字符串拼接,self 為當前聚集函數的指針,用來與前面的計算結果進行關聯 ??MEMBER?FUNCTION?ODCIAGGREGATEITERATE(self?????IN?OUT?wy_wm_concat, ???????????????????????????????????????colValue?IN?VARCHAR2)?RETURN?NUMBER?is ????tempStr?varchar(500); ????extendStr?varchar(500); ????deStr?varchar(100); ????deLen?int?default?0; ????segStr?varchar(500); ????--定義一個二維數組 ????TYPE varArry?IS?VARRAY(2)?OF?VARCHAR2(200); ????tempArry varArry := varArry('',?''); ??begin ????if instr(colValue,?' ', 1) > 0?then ??????tempStr := substr(colValue, 1, instr(colValue,?' ', 1) - 1); ????else ??????tempStr := colValue; ????end?if; ????--排序和分隔符 ????extendStr :=?REPLACE(colValue, tempStr ||?' '); ????if instr(extendStr,?' ', 1) > 0?then ??????tempArry(1) := substr(extendStr, 1, instr(extendStr,?' ', 1) - 1); ??????tempArry(2) := substr(extendStr, instr(extendStr,?' ', 1)); ??????for?i?in?1 .. tempArry.count?loop ????????-- 獲取分隔符 ????????if (tempArry(i)?is?not?null)?and ???????????(instr(tempArry(i),?'delimiter=>') > 0)?THEN ??????????deStr :=?'delimiter=>'; ??????????deLen := length(deStr); ??????????segStr := substr(trim(tempArry(i)), ???????????????????????????instr(trim(tempArry(i)), deStr) + deLen); ??????????self.delimiter := SUBSTR(segStr, 1, instr(segStr,?';', -1) - 1); ????????END?IF; ????????-- 獲取排序字符串 ????????if tempArry(i)?is?not?null?and ???????????(instr(tempArry(i),?'orderby=>') > 0)?THEN ??????????deStr :=?'orderby=>'; ??????????deLen := length(deStr); ??????????segStr := substr(trim(tempArry(i)), ???????????????????????????instr(trim(tempArry(i)), deStr) + deLen); ??????????self.orderby := SUBSTR(segStr, 1, instr(segStr,?';', -1) - 1); ????????END?IF; ??????end?loop; ????end?if; ????-- 存放入數組 ????self.strArray.extend; ????self.strArray(self.strArray.count) := tempStr; ????return?ODCICONST.Success; ??END; ??--并行操作是用來合并兩個聚集函數的兩個不同的指針對應的結果 ??MEMBER?FUNCTION?ODCIAGGREGATEMERGE(self?IN?OUT?wy_wm_concat, ?????????????????????????????????????next?wy_wm_concat)?RETURN?NUMBER?is ??begin ????-- 將next數組中元素全部放入self指針對應的數組中 ????for?i?in?1 ..?next.strArray.count?loop ??????self.strArray.extend; ??????self.strArray(self.strArray.count) :=?next.strArray(i); ????end?loop; ????return?ODCICONST.Success; ??END; ??-- 終止函數,返回結果 ??MEMBER?FUNCTION?ODCIAGGREGATETERMINATE(self????????IN?wy_wm_concat, ?????????????????????????????????????????returnValue?OUT?VARCHAR2, ?????????????????????????????????????????flags???????IN?NUMBER)?RETURN?NUMBER?IS ????temp_rtnValue varchar2(32767); ??BEGIN ????-- 排序 ????if INSTR(self.orderby,?'desc') > 0?THEN ??????for?x?in?(select?column_value ??????????????????from?Table(self.strArray) ?????????????????order?by?1?DESC) loop ????????temp_rtnValue := temp_rtnValue || self.delimiter || x.column_value; ??????end?loop; ????ELSE ??????for?x?in?(select?column_value?from?Table(self.strArray)?order?by?1?ASC) loop ????????temp_rtnValue := temp_rtnValue || self.delimiter || x.column_value; ??????end?loop; ????END?IF; ????returnValue := ltrim(temp_rtnValue, self.delimiter); ????return?ODCICONST.Success; ??END; END;

(4)自定義聚集函數

1 2 3 -- 定義聚集函數(未開啟并行計算功能) create?or?replace?function?wy_concat(colValue? VARCHAR2)?RETURN?VARCHAR2 ??AGGREGATE USING wy_wm_concat;

? 至此,主要的代碼已經全部奉上,看看運行效果,如下截圖:

? ①看看調用的默認情況(分隔符默認是逗號,排序默認是升序,在初始化函數中如此定義的)

??

? ?②自定義分隔符(利用分隔符函數將分隔符定義為*)

??

? ?③降序排序

? ?

? ? ④去重,為了可以使用wm_concat自帶的去重函數,所以在自定義分隔符和排序函數時,實質是實用了字符串處理(如果你覺得處理字符串麻煩,可以自定義 type... as object ,在使用的時候可以很方便,不會用的童鞋可以私下問)

? ?

總結

以上是生活随笔為你收集整理的重写Oracle的wm_concat函数,自定义分隔符、排序的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。