我已经通过几个不同的帖子试图找到解决方案。我有一个列,其中包含遵循以下格式的说明:
String<Numeric>
然而,该专栏并不局限于前面提到的一套格式,可能就像
UNI<01> JPG<84>
JPG<84> UNI<01>
JPG<84>
UNI<01>
其他变化没有任何受控模式。
我需要做的是提取&lt;&gt;之间的数字基于&lt;&gt;之前的字符串进入另一个表中的单独列。所以UNI会将以下数字限定为某个table.column,而JPG会限定另一个表等。我已经看到了提取数字但不符合条件的函数,如果前面有给定的限定符字符串,则只提取数字
答案 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 <> ''