oralce逗號分割變多行 Oracle中REGEXP_SUBSTR函數


Oracle中REGEXP_SUBSTR函數的使用說明:
 
題目如下:
在oracle中,使用一條語句實現將'17,20,23'拆分成'17','20','23'的集合。
 
REGEXP_SUBSTR函數格式如下:
function REGEXP_SUBSTR(String, pattern, position, occurrence, modifier)
__srcstr     :需要進行正則處理的字符串
__pattern    :進行匹配的正則表達式
__position   :起始位置,從第幾個字符開始正則表達式匹配(默認爲1)
__occurrence :標識第幾個匹配組,默認爲1
__modifier   :模式('i'不區分大小寫進行檢索;'c'區分大小寫進行檢索。默認爲'c'。)
 
1、查詢使用正則分割後的第一個值,也就是17
[sql] 
SELECT REGEXP_SUBSTR('17,20,23','[^,]+',1,1,'i') AS STR FROM DUAL;  
結果:  www.2cto.com  
STR
-----
17
 
2、查詢使用正則分割後的最後一個值,也就是23
[sql] 
SELECT REGEXP_SUBSTR('17,20,23','[^,]+',1,3,'i') AS STR FROM DUAL;  
結果:
STR
----
23
 
3、獲取一個多個數值的列,從而能夠讓結果以多行的形式展示出來
[sql] 
SELECT LEVEL FROM DUAL CONNECT BY LEVEL <=7;  
結果:  www.2cto.com  
LEVEL
----
1
2
3
4
5
6
7
 
4、將上面REGEXP_SUBSTR的occurrence關聯
[sql] 
SELECT NVL(REGEXP_SUBSTR('17,20,23', '[^,]+', 1, LEVEL, 'i'), 'NULLL') AS STR  
  FROM DUAL  
CONNECT BY LEVEL <= 7;  
STR  www.2cto.com  
----
17
20
23
NULL
NULL
NULL
NULL
 
5、優化上面的SQL語句,讓生成的行的數量符合實際情況
[sql] 
SELECT REGEXP_SUBSTR('17,20,23', '[^,]+', 1, LEVEL, 'i') AS STR  
  FROM DUAL  
CONNECT BY LEVEL <=  
           LENGTH('17,20,23') - LENGTH(REGEXP_REPLACE('17,20,23', ',', ''))+1;  
STR
----
17
20
23


oralce逗號分割變多行

 

方法一

select  a.*  , 

REGEXP_SUBSTR(a.rolecode ,'[^,]+',1,l) AS rolecode 

from p_user a,(SELECT LEVEL l FROM DUAL CONNECT BY LEVEL<=100) b

WHERE l <=LENGTH(a.rolecode) - LENGTH(REPLACE(rolecode,','))+1

   www.2cto.com  

使用函數REGEXP_SUBSTR拆分字符串:

 

5個參數

 

第一個是輸入的字符串

 

第二個是正則表達式

 

第三個是標識從第幾個字符開始正則表達式匹配。(默認爲1)

 

第四個是標識第幾個匹配組。(默認爲1)

 

第五個是是取值範圍:

i:大小寫不敏感;

 

c:大小寫敏感;

 

n:點號 . 不匹配換行符號;

 

m:多行模式;

 

x:擴展模式,忽略正則表達式中的空白字符。

 

SELECT a.*,REGEXP_SUBSTR(servicereqid ,'[^;]+',1,l) AS servicereq

  FROM sum_portal_satisfaction a,(SELECT LEVEL l FROM DUAL CONNECT BY LEVEL<=100) b

WHERE l <=LENGTH(servicereqid) - LENGTH(REPLACE(servicereqid,';'))+1

ORDER BY 1,2;

 

----SELECT LEVEL l FROM DUAL CONNECT BY LEVEL<=100; 生成1到100的數據行。

----l <=LENGTH(servicereqid) - LENGTH(REPLACE(servicereqid,';'))+1,注意此處是‘L’並非‘1’,上面的REGEXP_SUBSTR的第四個參數也一樣。

 

 

---下面爲拆分字符串,再進行的行轉列

create or replace view v_sum_portal_satisfaction_sr as

select 

survey_type,

survey_time,

center_code,

center_name,

city_id,

city_name,

REGEXP_SUBSTR(servicereqid ,'[^;]+',1,l) AS servicereqid,

REGEXP_SUBSTR(servicereqname ,'[^;]+',1,l) AS servicereqname,

sum(decode(survey_value,0, sur_times,null)) giveup_times,--調查值 -1:未處理 0:用戶放棄 1:很滿意 2.滿意 3.對csr不滿意 4.對其它不滿意

sum(decode(survey_value,1, sur_times,null))vsatis_times,

sum(decode(survey_value,2, sur_times,null))satis_times,

sum(decode(survey_value,3, sur_times,null))ncsr_times,

sum(decode(survey_value,4, sur_times,null))nelse_times,

sum(sur_times) sur_times

  FROM sum_portal_satisfaction a,(SELECT LEVEL l FROM DUAL CONNECT BY LEVEL<=100) b

WHERE l <=LENGTH(servicereqid) - LENGTH(REPLACE(servicereqid,';'))+1

group by

subslevelid,

center_code,

center_name,

city_id,

city_name,

survey_type,

survey_time,

servicereqid,

servicereqname,l

 

方法二:

 

create table  testTable (

       id  nvarchar2(200) primary key not null ,

       content  nvarchar2(200) not null 

)

 

insert into  testTable values ('4','館內idx_10館外idx_11總體idx_12');

 

 

select *  from table ( CAST (fn_split(('館內idx_1$館外idx_2$總體idx_3$') ,'$') as ty_str_split  )  )

 

select * from testtable b left join  table (fn_split((content), '$')   ) a   on 1=1;

 

--實現split函數

CREATE OR REPLACE TYPE ty_str_split IS TABLE OF VARCHAR2 (4000);

 

CREATE OR REPLACE FUNCTION fn_split (p_str IN VARCHAR2, p_delimiter IN VARCHAR2)

    RETURN ty_str_split

IS

    j INT := 0;

    i INT := 1;

    len INT := 0;

    len1 INT := 0;

    str VARCHAR2 (4000);

    str_split ty_str_split := ty_str_split ();

BEGIN

    len := LENGTH (p_str);

    len1 := LENGTH (p_delimiter);

 

    WHILE j < len

    LOOP

        j := INSTR (p_str, p_delimiter, i);

 

        IF j = 0

        THEN

            j := len;

            str := SUBSTR (p_str, i);

            str_split.EXTEND;

            str_split (str_split.COUNT) := str;

 

            IF i >= len

            THEN

                EXIT;

            END IF;

        ELSE

            str := SUBSTR (p_str, i, j - i);

            i := j + len1;

            str_split.EXTEND;

            str_split (str_split.COUNT) := str;

        END IF;

    END LOOP;

 

    RETURN str_split;

END fn_split;

 

DECLARE

    CURSOR c

    IS

select *  from table ( CAST (fn_split(('館內idx_1$館外idx_2$總體idx_3$') ,'$') as ty_str_split  )  );

 

    r c%ROWTYPE;

BEGIN

    OPEN c;

 

    LOOP

        FETCH c INTO r;

        EXIT WHEN c%NOTFOUND;

        DBMS_OUTPUT.put_line (r.column_value);

    END LOOP;

 

    CLOSE c;

END;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章