給Oracle添加split和splitstr函數

最近項目中有不少須要作批量操做的需求,客戶端把一組逗號分隔的ID字符串傳給數據庫,存儲過程就須要把它們分割,而後逐個處理。數據庫

以往的處理方式有以下幾種:oracle

一、在存儲過程內寫循環,逐個分析字符串中的ID,而後逐個處理。缺點:循環一次處理一個,若是每次判斷都不少,效率將很受影響。適合每次處理要作單獨判斷的狀況。函數

二、使用臨時表,先調用一個存儲過程將ID拆分並插入到臨時表中,而後結合臨時表能夠寫SQL一次處理多筆。缺點:須要插臨時表,效率不高,數據量越大影響越嚴重。spa

之前的項目用的最多的仍是第2中方式,畢竟方便,且效率比第1種好。 字符串

如今項目中用到了不少不少的批量操做,不少的重複代碼讓我不厭其煩。突然想到,.Net和JS中都有split相似的函數,拆分字符串很方便,oracle中要是也有這樣的功能該多好呀。it

多方查找資料發現,給oracle添加split函數是徹底能夠實現的,避免了插入臨時表,因此效率比上面的第2中方法效率高不少。io

後來我還添加了splitstr函數,能夠很方便獲取字符串中的指定節點。 table

有了這兩個函數,處理批量操做,真是如虎添翼,效率倍增,嘿嘿……效率

好了,閒話少說,上代碼!若有不妥之處,請各位前輩博友斧正。select

 1  /*
 2   * Oracle 建立 split 和 splitstr 函數
 3    */
 4 
 5  /*  建立一個表類型  */
 6  create  or  replace type tabletype  as  table  of  VARCHAR2( 32676)
 7  /
 8 
 9  /*  建立 split 函數  */
10  CREATE  OR  REPLACE  FUNCTION split (p_list CLOB, p_sep  VARCHAR2 : =  ' , ')
11     RETURN tabletype
12    PIPELINED
13  /* *************************************
14   * Name:        split
15   * Author:      Sean Zhang.
16   * Date:        2012-09-03.
17   * Function:    返回字符串被指定字符分割後的表類型。
18   * Parameters:  p_list: 待分割的字符串。
19                  p_sep: 分隔符,默認逗號,也能夠指定字符或字符串。
20   * Example:     SELECT *
21                    FROM users
22                   WHERE u_id IN (SELECT COLUMN_VALUE
23                                    FROM table (split ('1,2')))
24                  返回u_id爲1和2的兩行數據。
25   ************************************* */
26  IS
27    l_idx    PLS_INTEGER;
28    v_list    VARCHAR2 ( 32676) : = p_list;
29  BEGIN
30    LOOP
31       l_idx   : = INSTR (v_list, p_sep);
32 
33        IF l_idx  >  0
34        THEN
35           PIPE ROW (SUBSTR (v_list,  1, l_idx  -  1));
36          v_list   : = SUBSTR (v_list, l_idx  + LENGTH (p_sep));
37        ELSE
38           PIPE ROW (v_list);
39           EXIT;
40        END  IF;
41     END LOOP;
42  END;
43  /
44 
45  /*  建立 splitstr 函數  */
46  CREATE  OR  REPLACE  FUNCTION splitstr ( str  IN CLOB,
47                                        i    IN  NUMBER : =  0,
48                                        sep  IN  VARCHAR2 : =  ' , '
49 )
50     RETURN  VARCHAR2
51  /* *************************************
52   * Name:        splitstr
53   * Author:      Sean Zhang.
54   * Date:        2012-09-03.
55   * Function:    返回字符串被指定字符分割後的指定節點字符串。
56   * Parameters:  str: 待分割的字符串。
57                  i: 返回第幾個節點。當i爲0返回str中的全部字符,當i 超過可被分割的個數時返回空。
58                  sep: 分隔符,默認逗號,也能夠指定字符或字符串。當指定的分隔符不存在於str中時返回sep中的字符。
59   * Example:     select splitstr('abc,def', 1) as str from dual;  獲得 abc
60                  select splitstr('abc,def', 3) as str from dual;  獲得 空
61   ************************************* */
62  IS
63    t_i        NUMBER;
64    t_count    NUMBER;
65    t_str      VARCHAR2 ( 4000);
66  BEGIN
67     IF i  =  0
68     THEN
69       t_str   : =  str;
70    ELSIF INSTR ( str, sep)  =  0
71     THEN
72       t_str   : = sep;
73     ELSE
74        SELECT  COUNT (  * )
75        INTO t_count
76        FROM  table (split ( str, sep));
77 
78        IF i  <= t_count
79        THEN
80           SELECT  str
81           INTO t_str
82           FROM ( SELECT ROWNUM  AS item, COLUMN_VALUE  AS  str
83                 FROM  table (split ( str, sep)))
84           WHERE item  = i;
85        END  IF;
86     END  IF;
87 
88     RETURN t_str;
89  END;
90  /

相關文章
相關標籤/搜索