美文网首页
oracle 中 split 方法 分割字符串为多行记录

oracle 中 split 方法 分割字符串为多行记录

作者: 嘻哈哈_95fe | 来源:发表于2019-09-25 20:43 被阅读0次

        发现最近老是写vue的东西,仔细一想,我是个java程序员呀。这样划水不对呀。所以最近研究了一下在oracle中可能出现的一些情况的对策;

        其中,我发现有时候,我们在数据库中可能保存一些有规律的字符串,比如“123,321,4556,41324”类似这种,通过‘,’或者其他分隔符隔开的字符串值,但是我们业务需求是想要把这种字符串转换成[123,321,4556,41324]的数组格式,也就是查询出来的返回值是list<int>或者list<String>格式;

        按照正常的思路,我们都会先查询出一个String的值,然后在java中使用split方法来实现,但是我们今天不走寻常路,直接要在数据库中查询出一个数组;

        但是如何实现呢?oracle是没有split方法的,我首先想到的是自己实现一个split方法,然后在查询数据的时候直接调用方法就能实现了,但是这样不就跟先查询出来在split分割没啥区别了呢?不行,说好不走寻常路的;

        然后我发现oralce中对字符串处理的方法中常用的方法有replace,translate,substr等

        其中substr可能可以实现,那么我假设一下,我要使用SUBSTR(string,start, [length])方法实现切割字符串的话,那么我需要只要分隔符所在的index值,那么需要用indexof方法,但是oracle好像没有提供这个方法,找了一下,发现有个instr( string1, string2 [, start_position [, nth_appearance ] ] ) 方法,字符串1中字符串2在第start_position 次出现的index;nth_appearance是查找方向,1是正向,-1是反向,那么我可以用instr先获取到分隔符出现的位置,然后再使用substr函数,但是每次使用的时候都需要获取到第n和n+1个分隔符的位置来获取截取长度,用起来好像不太方便,在sql里面不太好写;

        于是我有没有什么其他的招式可以更方便的实现,嘿,我还真找到一个比较方便的方法:

        REGEXP_SUBSTR(string, pattern, position, occurrence, modifier)

        使用正则匹配截取字符串的方法,这个方法用的比较少,但是这个方法比substr方法更方便的地方就在于它是直接使用分隔符分割所有字符串,所以不需要分隔符的index也不需要知道截取长度,就他了;

        这个方法怎么用呢?举个栗子:

    SELECT REGEXP_SUBSTR('123,321,4556,41324', '[^,]+') FROM DUAL;

    ->>        123

        我们匹配正则‘,’号开始,多个逗号,由于正则不太熟,哈哈,后面两个参数先不用,那么我得到了字符串中分隔符隔开的第1个子字符串,后面两个参数是什么作用呢?其中第三个参数position是分割后的字符串起点的index,这里的index是从1开始的,第四个参数很重要,是分隔开之后的第几个字符串,也就相当于我们数组的下标,当然也是从1开始的;最后一个参数我觉得应该用的时候比较少,是用作忽略大小写的,默认是不忽略,需要忽略大小写的话就加上‘i’来标识;

        这样之后,我们只需要用一个i++循环来获取第四个参数的值,就能得到我们所需的数组了

        DECLARE

      X NUMBER;

      Y NUMBER;

    BEGIN

      X := 0;

      WHILE X < 4 LOOP

        X := X + 1;

        SELECT REGEXP_SUBSTR('123,321,4556,41324', '[^,]+',1,X) INTO Y FROM DUAL;

        DBMS_OUTPUT.PUT_LINE(Y);

      END LOOP;

    END;

    ->>123

    ->>321

    ->>4556

    ->>41324

     结果这又变成了一个存储过程了,而且到底需要分割出几个字符串是事前不知道的,这样不行,想想有没有其他简单点的实现方法呢?

        这是我突然想到了一个,之前我不是写过一个connect by吗?connect by的时候不是有一个level值吗?每一层递归的level正好拿来当做每一次数组下标使用,于是我简化出了如下方法:

    SELECT REGEXP_SUBSTR('123,321,4556,41324', '[^,]+', 1, LEVEL)

      FROM DUAL

    CONNECT BY REGEXP_SUBSTR('123,321,4556,41324', '[^,]+', 1, LEVEL) IS NOT NULL;

        在获取结果为null的时候终止递归,哈哈,完美实现了不走寻常路的结果;

    相关文章

      网友评论

          本文标题:oracle 中 split 方法 分割字符串为多行记录

          本文链接:https://www.haomeiwen.com/subject/llzjyctx.html