给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  /

相关文章
相关标签/搜索