2013-09-23 1417 views
4

如何分割DB2中的字符串值?如何根據DB2中的分隔符分割字符串值

例如,給定的值:

CHG-FFH. 

我想要分割的破折號( - ),這將導致在兩個值:

CHG 
FFH. 

採用分體式的功能,但它我試圖在DB2中不是一個函數。

任何幫助將不勝感激。

回答

3

這就是我想和它拿來我有效的結果。因此與所有人共享。

select column_name, substr(column_name,1,locate('-',column_name)-1), 
substr(column_name,locate('-',column_name)+1, 
length(substr(column_name,locate('-',column_name)+1))) from 
table_name where column_name is not null and column_name!='' 
and column_name like '%-%' 
3

嘗試着這樣一句話:

select substr(your_value, 1,3), substr(your_value, 4, 3) from your_table 
+0

@彼得:感謝您的答覆。您提供的解決方案僅適用於上述提及的值,例如CHG-FFH。但是如果字符在「 - 」之前和之後不固定,那麼可以暗示什麼解決方案? – sTg

+0

試約什船體的溶液 –

13

簡短的回答:

你需要找到 分隔符的位置,然後串之前和之後。

SELECT 
    SUBSTR('CHG-FFH', 1,LOCATE('-','CHG-FFH')-1) as FIRST_PART 
    , SUBSTR('CHG-FFH', LOCATE('-','CHG-FFH')+1) as SECOND_PART 
FROM SYSIBM.SYSDUMMY1; 

龍答:

DB2,與其它關係數據庫以及不提供一個函數來做到這一點。

原因可能是它不是一個隱式標量函數。如果你的字符串中有不止一個破折號,你想分成三部分嗎?四?因此,第一步是記錄您的數據是否確定 - 如果它有特定數量的組件需要拆分。在你的例子中,你有兩個,所以我會從這個假設開始,然後評論你將如何處理其他情況。

方案:由一個分隔符

分開只有兩個部件兩個部分組成的字符串值,你需要找到的分隔符的位置,然後通過使用前後位置串之前和之後在一個子字符串函數中。

  1. LOCATE您的分隔符的索引。
LOCATE('-','CHG-FFH') 

注: DB2提供了可用於該兩種功能:POSITION(或POSSTR),和LOCATE(或LOCATE_IN_STRING)。 LOCATE有點強大,因爲它允許您指定一個開始位置,如果您有多個分隔符,這將會很有幫助。

  1. SUBSTR使用分隔符索引。

在第一部分中,在位置1啓動子,最多的分隔符之前的字符(分隔符位置 - 1):

SUBSTR('CHG-FFH', 1,LOCATE('-','CHG-FFH')-1) as FIRST_PART 

對於第二部分,在該位置啓動子定界符索引後(定界符位置+ 1),並獲得字符串的其餘部分:

SUBSTR('CHG-FFH', LOCATE('-','CHG-FFH')+1) as SECOND_PART 

最終結果:

SELECT 
    SUBSTR('CHG-FFH', 1,LOCATE('-','CHG-FFH')-1) as FIRST_PART 
    , SUBSTR('CHG-FFH', LOCATE('-','CHG-FFH')+1) as SECOND_PART 
FROM SYSIBM.SYSDUMMY1; 

方案:由一個分隔符

分開三個部分組成的字符串值,使用相同的概念,第一個場景,但你必須確定第二限定的指標。使用第一個分隔符的索引指定一個起點:需要注意的是LOCATE允許指定起始位置:

>>-LOCATE(search-string,source-string-+--------+-+--------------------+-)->< 
             '-,start-' '-,--+-CODEUNITS16-+-'  
                 +-CODEUNITS32-+  
                 '-OCTETS------' 

尋找第二限定:

使用第一分隔符的位置找到第二個分隔符的起點。

LOCATE('-','CHG-FFH-EEE', LOCATE('-','CHG-FFH-EEE')+1) 

使用,作爲一個SUBSTR點,第二和第三值,以及你所有的設置。注意:對於第二個值,您必須使用兩個分隔符位置來對該值進行子字符串。

最終結果:

SELECT 
    SUBSTR('CHG-FFH-EEE', 1,LOCATE('-','CHG-FFH-EEE')-1) as FIRST_PART 
    , SUBSTR('CHG-FFH-EEE', LOCATE('-','CHG-FFH-EEE')+1, LOCATE('-','CHG-FFH-EEE', LOCATE('-','CHG-FFH-EEE'))-1) as SECOND_PART 
    , SUBSTR('CHG-FFH-EEE', LOCATE('-','CHG-FFH-EEE', LOCATE('-','CHG-FFH-EEE')+1)+1) as THIRD_PART 
FROM SYSIBM.SYSDUMMY1; 

你可以看到這個策略將變得不可收拾在您的字符串分隔符的數量更多。

場景:分隔符

這是最好用存儲過程接近一個棘手的問題的數量不定。仔細考慮一下這樣的事情:你想如何將解析出的數據從算法中提取出來,你將如何訪問數據?數組不是SQL中的本地類型,但它們在存儲過程中,那麼當您將字符串中的所有部分解析出來時,如何處理數組?接近這種情況下

一種方法是在這裏找到答案:

Split a VARCHAR in DB2 to retrieve a value inside

+0

能的第二部分是: SUBSTR( 'CHG-FFH-EEE',LOCATE( ' - ', 'CHG-FFH-EEE')+ 1,LOCATE( ' - ','CHG-FFH -EEE',LOCATE(' - ','CHG-FFH-EEE')) - 1)as SECOND_PART – user3606336

+0

是的!沒錯,@ user3606336。在我之前沒有注意到我的例子沒有正常工作。我會通過您的更正更新我的答案。謝謝! –

0

如果確定每個子串爲3個字符長可以嘗試這個代碼,只要TABLE1是一個表,其中存在至少X行(X = 10在此實例中):

select rc, substr(string_to_split, (rc-1)*3+rc, 3) as result from 
    (select row_number() over() as rc from TABLE1 fetch first 10 rows only) TB_rowcount 
    cross join 
    (select 'CHG-FFH' as string_to_split from sysibm.sysdummy1) T2 
    where substr(string_to_split, (rc-1)*3+rc, 3) <> ' ' 

如果字符串的長度是不一樣的,你必須申請LOCATE功能找到分隔

0

我知道這是舊的帖子..但認爲以下可能會幫助別人。

我用下面的方法拆分給定的字符串。

SELECT TRIM(ITEM) AS ITEM FROM TABLE(<LIB1>.SF_SPLIT(I_INPUTLIST=>'AA|BB|CC|DD|EE|EE|FF', I_DELIMITER=>'|')) AS T; 

SF_SPLIT is the User defined SQL function and below is definition: 

CREATE OR REPLACE FUNCTION <LIB1>.SF_SPLIT(

    I_INPUTLIST VARCHAR(8000) 
    , I_DELIMITER VARCHAR(3)  

) 
RETURNS TABLE (ITEM VARCHAR(8000)) 

LANGUAGE SQL 

RETURN 

WITH R1 (ITEM, REMINDER) AS 

(SELECT SUBSTR(I_INPUTLIST, 1, LOCATE(I_DELIMITER, I_INPUTLIST)-1) AS ITEM, 

SUBSTR(I_INPUTLIST, LOCATE(I_DELIMITER, I_INPUTLIST)+1, LENGTH(I_INPUTLIST)) REMINDER 

FROM SYSIBM.SYSDUMMY1 

UNION ALL 

SELECT SUBSTR(REMINDER, 1, LOCATE(I_DELIMITER, REMINDER)-1) AS ITEM, 
SUBSTR(REMINDER, LOCATE(I_DELIMITER, REMINDER)+1, LENGTH(REMINDER)) REMINDER 

FROM R1 WHERE LOCATE(I_DELIMITER, REMINDER) > 0 

UNION ALL 

SELECT SUBSTR(REMINDER, LOCATE(I_DELIMITER, REMINDER)+1, LENGTH(REMINDER)) AS ITEM, 

'' AS REMINDER FROM R1 WHERE REMINDER <> '' AND LOCATE(I_DELIMITER, REMINDER) = 0 

) 

SELECT ITEM FROM R1; 
0

我需要使用instr,substr,trim和使用locate定位以及..但instr和substr都支持。你可以找到一個模式。我不得不通過一個帶' - '的varchar分割,並且需要找到結尾並從那裏返回。

  select itn, 
      substr(Message, 1 , locate(' - ', Message)) FIRST_SSR, 
      SUBSTR(Message , instr(message, ' - ', octets)+1, (instr( 
      message, '(Ref', octets)+1)) SECOND_STR , 
      Message 
       from 
     (
    select p.itn itn, 
      substr(p.msg, instr(p.msg, ' - ' , octets)+21) Message 
    from itnpad p 
    where p.msg like '%MR - Multiple Requests%' 

     ) A 
0

在DB2

SELECT 
'11,222,33,444' AS THE_F_STRING 
, SUBSTR('11,222,33,444', 1, LOCATE_IN_STRING('11,222,33,444',',',1,1)-1) AS AA 
, SUBSTR('11,222,33,444', LOCATE_IN_STRING('11,222,33,444',',',1,1)+1, LOCATE_IN_STRING('11,222,33,444',',',1,2)-LOCATE_IN_STRING('11,222,33,444',',',1,1)-1) AS BB 
, SUBSTR('11,222,33,444', LOCATE_IN_STRING('11,222,33,444',',',1,2)+1, LOCATE_IN_STRING('11,222,33,444',',',1,3)-LOCATE_IN_STRING('11,222,33,444',',',1,2)-1) AS CC 
, SUBSTR('11,222,33,444', LOCATE_IN_STRING('11,222,33,444',',',1,3)+1, LENGTH('11,222,33,444')-LOCATE_IN_STRING('11,222,33,444',',',1,3)) AS DD 
FROM SYSIBM.SYSDUMMY1; 

保持外推... ...享受