提前感谢您的帮助。我需要帮助编写SSIS脚本组件来将单行划分为多行。我看到了许多有用的博客和帖子:
http://bi-polar23.blogspot.com/2008/06/splitting-delimited-column-in-ssis.html
但是,我需要一些额外的帮助才能完成项目的编码。基本上这就是我想做的事。
输入数据
ID Item Name 1 Apple01,02,Banana01,02,03 2 Spoon1,2,Fork1,2,3,4
输出数据
ParentID ChildID Item Name 1 1 Apple01 1 2 Apple02 1 3 Banana01 1 4 Banana02 1 5 Banana03 2 1 Spoon1 2 2 Spoon2 2 3 Fork1 2 4 Fork2 2 5 Fork3 2 6 Fork4
以下是我尝试编码,但如果它不合逻辑,请随时修改整体。 SSIS异步输出已设置。
Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)
Dim posID As Integer, childID As Integer
Dim delimiter As String = ","
Dim txtHolder As String, suffixHolder As String
Dim itemName As String = Row.ItemName
Dim keyField As Integer = Row.ID
If Not (String.IsNullOrEmpty(itemList)) Then
Dim inputListArray() As String = _
itemList.Split(New String() {delimiter}, _
StringSplitOptions.RemoveEmptyEntries)
For Each item As String In inputListArray
Output0Buffer.AddRow()
Output0Buffer.ParentID = keyField
If item.Length >= 3 Then
txtHolder = Trim(item)
Output0Buffer.ItemName = txtHolder
'when item length is less than 3, it's suffix
Else
suffixHolder = Trim(item)
txtHolder = Left(txtHolder.ToString(), Len(txtHolder) _
- Len(suffixHolder)) & suffixHolder.ToString()
Output0Buffer.ItemName = txtHolder
End If
Next
End If
End Sub
ID Item Name 1 Apple01 1 02 1 Banana01 1 02 1 03 2 Spoon1 2 2 2 Fork1 2 2 2 3 2 4
答案 0 :(得分:8)
如果我在这个回答中表现得很迂腐,那不是我的意图。根据评论“我是新编码和故障排除问题”,我想了解我的观察以及我是如何找到它们的。
希望根据与行关联的分隔字段将单行拆分为多个输出行。
现在的代码是生成适当的行数,因此您可以使脚本的异步部分(拆分)正常工作,这是一个加号。需要做的是我们需要1)填充子ID列2)在生成子项时将项前缀应用于所有后续行。
我对待这样的大多数问题。我想要完成什么?什么工作?什么不起作用?需要做些什么才能使其发挥作用。将问题分解为越来越小的问题最终会导致您可以做的事情。
在提供的代码中粘贴导致错误,即未声明itemList。根据用法,似乎它的目的是itemName。
修复之后,您应该注意到IDE指示您有2个未使用的变量(posID,childID),并且variable txHolder is used before it's been assigned a value. A null reference exception could result at runtime.
我的同事经常评论警告是尚未成长的错误,所以我给您的建议作为一个初出茅庐的开发人员,要注意警告,除非你明确指望编译器警告你所说的情况。
在解决Child ID情况与名称前缀/后缀之间做出选择时,我会先从一个简单的问题开始,即孩子ID
这是一个花哨的标题短语,如果你搜索过你,你会对ssistalk或sqlis或任何一些非常聪明的博主提供大量的点击。魔鬼当然知道要搜索什么。没有你在哪里计算或将子id值分配给流,这当然是它没有出现在那里的原因。
我们只需要生成一个单调递增的数字,每次源ID更改时都会重置。我假设入站数据在传入数据中是唯一的,例如销售发票号码是唯一的,我们将拆分购买的物品。但是,如果在数据集中重复这些ID,则可能不是代表发票号,而是代表销售员ID。销售人员1可以在销售蔬菜的批次中有另一行。这是一个更复杂的场景,如果更好地描述您的源数据,我们可以重新审视。
生成我们的代理键有两个部分(同样,将问题分解成更小的部分)。要做的第一件事就是制作一个从1到N的数字。你已经定义了一个childId
变量来为此服务。初始化此变量(1),然后在foreach循环内增加它。
现在我们计算,我们需要将该值推送到输出流。将这两个步骤放在一起看起来像
childID = 1
For Each item As String In inputListArray
Output0Buffer.AddRow()
Output0Buffer.ParentId = keyField
Output0Buffer.ChildId = childID
' There might be VB shorthand for ++
childID = childID + 1
运行包并成功!从列表中抓取生成代理键。
我不知道在问题的另一半需要做什么的奇特术语,但我需要一些标题。鉴于源数据,这个可能更难以正确。您已经提供了Apple01,Banana01,Spoon1,Fork1的价值。看起来那里有一个模式(名称与代码连接)但是它是什么?您的代码表明,如果它小于3,则它是后缀,但您如何知道 base 是什么?第一行使用前导0并且是两位数长,而第二行不使用前导零。这是您需要了解数据的地方。识别第一行“代码”部分的规则是什么?一些可能的算法
除了修复局部变量ItemName / itemList之外,我没有做任何更改以使生成的项名称有效。最终代码通过删除PosID并将txtHolder初始化为空字符串来消除警告。
Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)
Dim childID As Integer
Dim delimiter As String = ","
Dim txtHolder As String = String.Empty, suffixHolder As String
Dim itemName As String = Row.ItemName
Dim keyField As Integer = Row.ID
If Not (String.IsNullOrEmpty(itemName)) Then
Dim inputListArray() As String = _
itemName.Split(New String() {delimiter}, _
StringSplitOptions.RemoveEmptyEntries)
' The inputListArray (our split out field)
' needs to generate values from 1 to N
childID = 1
For Each item As String In inputListArray
Output0Buffer.AddRow()
Output0Buffer.ParentId = keyField
Output0Buffer.ChildId = childID
' There might be VB shorthand for ++
childID = childID + 1
If item.Length >= 3 Then
txtHolder = Trim(item)
Output0Buffer.ItemName = txtHolder
Else
'when item length is less than 3, it's suffix
suffixHolder = Trim(item)
txtHolder = Left(txtHolder.ToString(), Len(txtHolder) _
- Len(suffixHolder)) & suffixHolder.ToString()
Output0Buffer.ItemName = txtHolder
End If
Next
End If
End Sub