[DB2] 스트링을 특정 구분자로 분리하여 테이블로 리턴하는 함수

Programming/Database 2010.08.11 댓글 Joshua95

특정 구분자로 나눠진 스트링을 테이블의 데이터로 뽑아주는 함수가 필요해서 이래저래 찾아보아 다음과 같이 만들었습니다.
원하는 기능은 이랬지요.
'1;2;3' 과 같은 스트링을 입력하면 1,2,3의 Data가 테이블에 입력되도록 하는 것이지요.

우선 아래의 fnGetElementIdx, fnGetElements 함수를 추가해 주고,
실제 사용은 아래와 같은 쿼리를 사용하여 사용하면 됩니다.

SELECT CAST(t.elem AS VARCHAR(256))
FROM TABLE ( fnGetElements('1;2;3',';') ) AS t(elem)



-----------------------------------------------------
-- 1. 스트링의 구분자 위치 정보를 생성, 리턴 (fnGetElements에서 사용)
-- http://www.ibm.com/developerworks/data/library/techarticle/0303stolze/0303stolze1.html#listing2
-----------------------------------------------------

CREATE FUNCTION fnGetElementIdx ( string CLOB(64K), delimiter VARGRAPHIC(1)  )
RETURNS TABLE ( ordinal INTEGER, index INTEGER )
LANGUAGE SQL
BEGIN ATOMIC
   RETURN
      WITH t(ordinal, index) AS
         ( VALUES ( 0, 0 )
           UNION ALL
           SELECT ordinal+1, COALESCE(NULLIF(
                     -- find the next delimiter ','
                     LOCATE(delimiter, string, index+1), 0),
                     LENGTH(string)+1)
           FROM   t
                  -- to prevent a warning condition for infinite
                  -- recursions, we add the explicit upper
                  -- boundary for the "ordinal" values
           WHERE  ordinal < 10000 AND
                  -- terminate if there are no further delimiters
                  -- remaining
                  LOCATE(delimiter, string, index+1) <> 0 )
      SELECT ordinal, index
      FROM   t
      UNION ALL
      -- add indicator for the end of the string
      SELECT MAX(ordinal)+1, LENGTH(string)+1
      FROM   t;
END;


-----------------------------------------------------
-- 2.스트링을 구분자로 분리하여 테이블로 리턴하는 함수
-- http://www.ibm.com/developerworks/data/library/techarticle/0303stolze/0303stolze1.html#listing2
-- ex1) select
-- SELECT 1, INT(CAST(t.elem AS VARCHAR(256))) , 2
-- FROM TABLE ( fnGetElements('1;2;3', ';') ) AS t(elem)

-- ex2) insert after select
-- INSERT INTO TBPROFILEOBJECTRELATION (SETTINGPROFILEID, OBJECTID, OBJECTTYPECODEID)
-- (
--    SELECT 1, INT(CAST(t.elem AS VARCHAR(256))) , 2
--    FROM TABLE ( fnGetElements('10;11;12;13;14;15;16;17;18;19', ';') ) AS t(elem)
-- )
-----------------------------------------------------

CREATE FUNCTION fnGetElements ( string CLOB(64K), delimiter VARGRAPHIC(1) )
RETURNS TABLE ( elements CLOB(64K) )
LANGUAGE SQL
BEGIN ATOMIC
  
   RETURN
      WITH t(ordinal, index) AS
         ( SELECT ordinal, index
           FROM   TABLE ( fnGetElementIdx(string, delimiter) ) AS x )
      SELECT SUBSTR(string, t1.index+1, t2.index - t1.index - 1)
      -- the join below makes sure that we have the lower and
      -- upper index where we can find each of the ',' delimiters
      -- that are separating the elements.  (For this, we exploit
      -- the additional indexes pointing to the beginning and end
      -- of the string.)
      FROM   t AS t1
      JOIN t AS t2
      ON t2.ordinal = t1.ordinal+1
      ORDER BY t1.ordinal;
               
END;

 

댓글