2013-09-23 230 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; 

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