복붙노트

[SQL] Oracle- 분할 문자열 쉼표 (문자열에 공백이 연속 쉼표를 포함)로 구분

SQL

Oracle- 분할 문자열 쉼표 (문자열에 공백이 연속 쉼표를 포함)로 구분

나는 ORACLE에서 쉼표로 구분 된 문자열을 분할하는 방법에 대한 해결책을 찾을 수 없습니다. 많이 검색, 아무것도 내 경우 작동하지 않습니다

암호

DECLARE
  TYPE T_ARRAY_OF_VARCHAR IS TABLE OF VARCHAR2(2000) INDEX BY BINARY_INTEGER;
  MY_ARRAY T_ARRAY_OF_VARCHAR;
  MY_STRING VARCHAR2(2000) := '12 3,456,,abc,def';
BEGIN
 FOR CURRENT_ROW IN (
    with test as    
      (select MY_STRING from dual)
      select regexp_substr(MY_STRING, '[^,]+', 1, rownum) SPLIT
      from test
      connect by level <= length (regexp_replace(MY_STRING, '[^,]+'))  + 1)

  LOOP
   DBMS_OUTPUT.PUT_LINE('>' || CURRENT_ROW.SPLIT || '<');
   --DBMS_OUTPUT.PUT_LINE(CURRENT_ROW.SPLIT);
    MY_ARRAY(MY_ARRAY.COUNT) := CURRENT_ROW.SPLIT;
  END LOOP;

  DBMS_OUTPUT.PUT_LINE('Array Size:' || MY_ARRAY.COUNT);
END;

/

출력은 다음과 같습니다

>12 3<
>456<
>abc<
>def<
><
Array Size:5

빈 값은 순서가있다 !!!!

해결법

  1. ==============================

    1.(가)리스트 부분을 구문 분석이보십시오. 그것은 널 (null)을 처리합니다

    (가)리스트 부분을 구문 분석이보십시오. 그것은 널 (null)을 처리합니다

    SQL> select regexp_substr('12 3,456,,abc,def', '(.*?)(,|$)', 1, level, null, 1) SPLIT, level
        from dual
        connect by level <= regexp_count('12 3,456,,abc,def',',') + 1
        ORDER BY level;
    
    SPLIT                  LEVEL
    ----------------- ----------
    12 3                       1
    456                        2
                               3
    abc                        4
    def                        5
    
    SQL>
    

    당신이 구문 분석 목록에 대한 정규식의 검색 할 때 불행하게도, 당신은 항상 널 (null)을 처리하지 않습니다 피해야한다이 양식을 발견 할 것이다 : '[^,] +'. 추가 정보를 원하시면 여기를 참조하십시오 : 분할 쉼표는 오라클의 열 값을 분리.

  2. ==============================

    2.XMLTABLE와 FLWOR expresion을보십시오. 다음의 예는 확보하고 쉼표없이 문자열을 넣으면 오류가 발생하지 않습니다. 그러나 이해하기 간단합니다.

    XMLTABLE와 FLWOR expresion을보십시오. 다음의 예는 확보하고 쉼표없이 문자열을 넣으면 오류가 발생하지 않습니다. 그러나 이해하기 간단합니다.

    select xmlcast(column_value as varchar2(2000))  value_list 
      from xmltable('for $val in ora:tokenize($strList,",") 
                      return $val' 
                     passing '12 3,456,,abc,def' as "strList"
                    ); 
    

    그리고 버전을 확보했다.

        select xmlcast(column_value as varchar2(2000)) value_list 
          from xmltable('for $val at $index in ora:tokenize(concat(",",$strList),",") 
           where $index > 1 
           return $val' passing '12 3,456,,abc,def' as "strList"
                   );
    
  3. ==============================

    3.쿼리 리틀 변경, 예를 들어, 당신이 MY_STRING에 존재하지 않습니다 하나 개의 문자를 선택할 수 있습니다 가정 파이프 |

    쿼리 리틀 변경, 예를 들어, 당신이 MY_STRING에 존재하지 않습니다 하나 개의 문자를 선택할 수 있습니다 가정 파이프 |

       with test as    
      (select '12 3,456,,,,abc,def' MY_STRING from dual)
      select trim('|' from regexp_substr(regexp_replace(MY_STRING,',,',',|,|'),'[^,]+',1,level)) SPLIT
      from test
      connect by level <= length (regexp_replace(MY_STRING, '[^,]+'))  + 1;
    

    산출:

     SPLIT                 
    -----------------------
    12 3                    
    456                     
    (null)                        
    (null)                         
    (null)                         
    abc                     
    def  
    
  4. ==============================

    4.PL / SQL의 필요, 당신은 일반 SQL에서 그것을 할 수 없었다. 참조 분할 쉼표는 오라클의 테이블에서 문자열을 구분.

    PL / SQL의 필요, 당신은 일반 SQL에서 그것을 할 수 없었다. 참조 분할 쉼표는 오라클의 테이블에서 문자열을 구분.

    MODEL 절을 사용하여 :

    WITH sample_data AS (
    SELECT '12 3,456,,,,,abc,def' str FROM dual
    )
    -- end of sample_data mimicking real table
    ,
    model_param AS (
    SELECT str AS orig_str ,
           ','
           || str
           || ','                                 AS mod_str ,
           1                                      AS start_pos ,
           Length(str)                           AS end_pos ,
           (LENGTH(str) -
           LENGTH(REPLACE(str, ','))) + 1        AS element_count ,
           0                                      AS element_no ,
           ROWNUM                                 AS rn
           FROM   sample_data )
           SELECT trim(Substr(mod_str, start_pos, end_pos-start_pos)) str
           FROM (
                 SELECT *
                 FROM   model_param
                 MODEL PARTITION BY ( rn, orig_str, mod_str)
                 DIMENSION BY (element_no)
                 MEASURES (start_pos, end_pos, element_count)
                 RULES ITERATE (2000)
                 UNTIL (ITERATION_NUMBER+1 = element_count[0])
               ( start_pos[ITERATION_NUMBER+1] =
                         instr(cv(mod_str), ',', 1, cv(element_no)) + 1,
                 end_pos[ITERATION_NUMBER+1] =
                         instr(cv(mod_str), ',', 1, cv(element_no) + 1) )
               )
            WHERE    element_no != 0
       ORDER BY      mod_str ,
                     element_no
       /
    

    산출

    STR
    ----------------------
    12 3
    456
    
    
    
    
    abc
    def
    
    8 rows selected.
    

    당신은 PL / SQL에서 그것을하고 싶은 경우에, 당신은 파이프 라인 테이블 기능을 사용할 수 있습니다 :

    SQL> CREATE OR REPLACE TYPE test_type
      2  AS
      3    TABLE OF VARCHAR2(100)
      4  /
    
    Type created.
    
    SQL> CREATE OR REPLACE FUNCTION comma_to_table(
      2      p_list IN VARCHAR2)
      3    RETURN test_type PIPELINED
      4  AS
      5    l_string LONG := p_list || ',';
      6    l_comma_index PLS_INTEGER;
      7    l_index PLS_INTEGER := 1;
      8  BEGIN
      9    LOOP
     10      l_comma_index := INSTR(l_string, ',', l_index);
     11      EXIT
     12    WHEN l_comma_index = 0;
     13      PIPE ROW ( TRIM(SUBSTR(l_string, l_index, l_comma_index - l_index)));
     14      l_index := l_comma_index                                + 1;
     15    END LOOP;
     16  RETURN;
     17  END comma_to_table;
     18  /
    
    Function created.
    

    하자의 출력을 참조하십시오

    SQL> SELECT *
      2  FROM TABLE(comma_to_table('12 3,456,,,,,abc,def'))
      3  /
    
    COLUMN_VALUE
    ------------------------------------------------------------------------------
    12 3
    456
    
    
    
    
    abc
    def
    
    8 rows selected.
    
    SQL>
    
  5. from https://stackoverflow.com/questions/35444250/oracle-split-string-comma-delimited-string-contains-spaces-and-consecutive-com by cc-by-sa and MIT license