SSIS子串提取基于限定符

时间:2014-11-04 16:49:41

标签: ssis expression

我已经通过几个不同的帖子试图找到解决方案。我有一个列,其中包含遵循以下格式的说明:

String<Numeric>

然而,该专栏并不局限于前面提到的一套格式,可能就像

UNI<01> JPG<84>
JPG<84> UNI<01>
JPG<84>
UNI<01>

其他变化没有任何受控模式。

我需要做的是提取&lt;&gt;之间的数字基于&lt;&gt;之前的字符串进入另一个表中的单独列。所以UNI会将以下数字限定为某个table.column,而JPG会限定另一个表等。我已经看到了提取数字但不符合条件的函数,如果前面有给定的限定符字符串,则只提取数字

3 个答案:

答案 0 :(得分:1)

您可以使用asynchronous Script Component输出包含在输入字符串中的每个type<value>标记的类型和值列的行。通过条件性拆分传递此组件的输出,以将每个类型定向到正确的目的地(例如表格)。

Pro:此方法可让您选择使用一个数据流同时处理所有标记类型,而每个标记类型需要一个数据流。

Con:涉及脚本组件,听起来您更愿意避免。

示例脚本组件代码

private readonly string pattern = @"(?<type>\w+)<(?<value>\d+)>";

public override void Input0_ProcessInputRow(Input0Buffer Row)
{
    foreach (Match match in Regex.Matches(Row.Data, pattern, RegexOptions.ExplicitCapture))
    {
        Output0Buffer.AddRow();
        Output0Buffer.Type = match.Groups["type"].Value;
        Output0Buffer.Value = match.Groups["value"].Value;
    }
}

注意:脚本组件需要使用两列创建的输出(可能名为Type和Value),然后将输出的SynchronousInputID属性设置为None)。

答案 1 :(得分:1)

根据问题评论中提到的范围限制,一次只需要找到一种类型的令牌(Foo,Bar,Blat等):您可以在派生列中使用表达式找到感兴趣的标记,然后在箭头之间提取值。

例如:

FINDSTRING([InputColumn], @[User::SearchToken] + "<", 1) == 0)?
    NULL(DT_WSTR, 1) :
    SUBSTRING([InputColumn], 
        FINDSTRING([InputColumn], @[User::SearchToken] + "<", 1) 
            + LEN(@[User::SearchToken]) + 1, 
        FINDSTRING(
                SUBSTRING([InputColumn], 
                    FINDSTRING([InputColumn], @[User::SearchToken] + "<", 1) 
                        + LEN(@[User::SearchToken]) +  1,
                LEN([InputColumn])
        ), ">", 1) - 1
    )

首先,表达式检查@[User::SearchToken]中指定的令牌是否在当前行中使用。如果是,则SUBSTRING用于输出箭头之间的值。如果不是,则返回NULL。

假设没有令牌的名称将以与另一个令牌的名称匹配的文本结束。搜索令牌将匹配栏&lt; 123&gt; FooBar&lt; 123&gt; 。容纳 Bar FooBar 作为不同的令牌是可能的,但必要的表达将会复杂得多。

答案 2 :(得分:0)

我最终为一个视图编写CTE来处理数据操作,然后处理SSIS包中的连接和其他数据。

;WITH RCTE (Status_Code, lft, rgt, idx)
AS (        SELECT  a.Status_code
                                            ,LEFT(a.Description,                        CASE WHEN CHARINDEX(' ', a.Description)=0 THEN LEN(a.Description)  ELSE CHARINDEX(' ', a.Description)-1 END) 
                                            ,SUBSTRING(a.Description,         CASE WHEN CHARINDEX(' ', a.Description)=0 THEN LEN(a.Description)  ELSE CHARINDEX(' ', a.Description)-1 END + 1, DATALENGTH(a.Description))
                                            ,0
            FROM   [disp] a WHERE NOT( Description IS  NULL OR Description ='')

            UNION ALL

            SELECT  r.Status_Code
                                            ,CASE WHEN CHARINDEX(' ', r.rgt) = 0 THEN r.rgt ELSE LEFT(r.rgt, CHARINDEX(' ', r.rgt) - 1) END
                                            ,CASE WHEN CHARINDEX(' ', r.rgt) > 0 THEN SUBSTRING(r.rgt, CHARINDEX(' ', r.rgt) + 1, DATALENGTH(r.rgt)) ELSE '' END
                                            ,idx + 1
            FROM   RCTE r 
            WHERE DATALENGTH(r.rgt) > 0 
)

SELECT  Status_Code
--                             ,lft,rgt                   -- Uncomment to see whats going on 
                            ,SUBSTRING(lft,0, CHARINDEX('<',lft)) AS [Description]
                            ,CASE WHEN ISNUMERIC(SUBSTRING(lft, CHARINDEX('<',lft)+1, LEN(lft)-CHARINDEX('<',lft)-1)) >0
                                              THEN      CAST (SUBSTRING(lft, CHARINDEX('<',lft)+1, LEN(lft)-CHARINDEX('<',lft)-1) AS INT) ELSE NULL END as Value 
FROM RCTE
where lft <> ''