在插入目标表期间,发生的任何错误都会重定向到错误表,我们可以在其中看到ErrorCode
和ErrorColumn
。问题是我们在ErrorColumn
中得到的值在包中的任何地方都不存在。也就是说,没有一列LineageID
等于ErrorColumn
。
稍后,虽然在每个列中逐个启用NULL条目,但我发现哪个列导致了问题。当我分析数据流任务内部的列时,它没有LineageID
中报告的ErrorColumn
。例如,报告的ErrorColumn
为413,但在第一次合并期间LineageID
为84,并且在各种排序期间会发生变化。无论如何,它永远不会变为413.此ErrorColumn
ID(413)根本不存在,但在错误重定向插入到目标源(错误表)期间会报告。
我检查了很多网站,但是他们都建议在脚本任务中通过ComponenteMetaData.InputCollection
或ComponentMetaData.OutputCollection
枚举,然后枚举列以查找LineageID
,但它是没有任何成功。
正如我所说,我已经解决了问题,但由于我们处于ETL过程的早期阶段,这可能会在其他一些情况下发生。如何解决这个问题?
答案 0 :(得分:7)
我正在复制我的答案,以便我们可以在网站上获得权威Q& A
What is the simple way to find the column name from Lineageid in SSIS
我记得说这不是那么难,我可以在错误重定向中编写一些脚本来从输入集合中查找列名。
string badColumn = this.ComponentMetaData.InputCollection[Row.ErrorColumn].Name;
我学到的是失败的列不在该集合中。好吧,但是报告的ErrorColumn不是我需要的。我找不到那个包,但这里有一个例子说明为什么我无法得到我需要的东西。希望你会有更好的运气。
这是一个简单的数据流,一旦它因为除零而到达派生列,就会产生错误。 Derived列生成一个新的输出列(LookAtMe)作为除法的结果。错误输出上的数据查看器告诉我失败的列是73.使用上面的脚本逻辑,如果我试图访问输入集合中的第73列,它将失败,因为它不在集合中。 LineageID 73是LookAtMe,LookAtMe不在我的错误分支中,它只在非错误分支中。
这是我的XML的副本,您可以看到,是的,outputColumn id 73是LookAtme。
<outputColumn id="73" name="LookAtMe" description="" lineageId="73" precision="0" scale="0" length="0" dataType="i4" codePage="0" sortKeyPosition="0" comparisonFlags="0" specialFlags="0" errorOrTruncationOperation="Computation" errorRowDisposition="RedirectRow" truncationRowDisposition="RedirectRow" externalMetadataColumnId="0" mappedColumnId="0"><properties>
我真的很想要这些数据而且我很聪明,所以我可以将所有结果合并在一起,然后有条件地将它拆分出来以获得它。问题是,Union All is an asynchronous transformation。异步转换导致数据从一组黄油复制到另一组,导致...分配了新的血统ID,因此即使使用联合将所有两个流重新组合在一起,您也无法调用数据流链找到原始的血统id,因为它在不同的缓冲区中。
在这一点上,我承认失败并决定我可以在我的包中没有智能/有用的错误报告。
2012年发布的SSIS改变了他们使用LineageID保持列同步的方式。它们不是将数字从源映射到接收器的组件,而是使用元素的文本表示。上面引用的XML现在看起来像
<outputColumn
refId="Package\DFT Generate Errors\DER Divide by SomeNumber.Outputs[Derived Column Output].Columns[LookAtMe]"
dataType="i4"
errorOrTruncationOperation="Computation"
errorRowDisposition="RedirectRow"
lineageId="Package\DFT Generate Errors\DER Divide by SomeNumber.Outputs[Derived Column Output].Columns[LookAtMe]"
name="LookAtMe"
truncationRowDisposition="FailComponent">
如果您现在查看ErrorColumn,它们甚至不会引用文本lineageid。相反,他们引用了第6列。如果我搜索源XML,我不会在任何地方找到对第6列的引用。它必须是一些运行时的魔法。
遗憾的是,净结果是相同的 - 您无法访问错误列,因为它是在此组件中创建的,因为它只存在于Output列集合中。它在错误列集合中不可用。
答案 1 :(得分:2)
我意识到这是一个迟到的答案,但我是SSIS游戏的新手。我已经创建了一个
的解决方案Check out the full solution here.
这是简短版本。
execsObj
和lineageIds
Dictionary<int, string> lineageIds = null;
public void Main()
{
// Grab the executables so we have to something to iterate over, and initialize our lineageIDs list
// Why the executables? Well, SSIS won't let us store a reference to the Package itself...
Dts.Variables["User::execsObj"].Value = ((Package)Dts.Variables["User::execsObj"].Parent).Executables;
Dts.Variables["User::lineageIds"].Value = new Dictionary<int, string>();
lineageIds = (Dictionary<int, string>)Dts.Variables["User::lineageIds"].Value;
Executables execs = (Executables)Dts.Variables["User::execsObj"].Value;
ReadExecutables(execs);
Dts.TaskResult = (int)ScriptResults.Success;
}
private void ReadExecutables(Executables executables)
{
foreach (Executable pkgExecutable in executables)
{
if (object.ReferenceEquals(pkgExecutable.GetType(), typeof(Microsoft.SqlServer.Dts.Runtime.TaskHost)))
{
TaskHost pkgExecTaskHost = (TaskHost)pkgExecutable;
if (pkgExecTaskHost.CreationName.StartsWith("SSIS.Pipeline"))
{
ProcessDataFlowTask(pkgExecTaskHost);
}
}
else if (object.ReferenceEquals(pkgExecutable.GetType(), typeof(Microsoft.SqlServer.Dts.Runtime.ForEachLoop)))
{
// Recurse into FELCs
ReadExecutables(((ForEachLoop)pkgExecutable).Executables);
}
}
}
private void ProcessDataFlowTask(TaskHost currentDataFlowTask)
{
MainPipe currentDataFlow = (MainPipe)currentDataFlowTask.InnerObject;
foreach (IDTSComponentMetaData100 currentComponent in currentDataFlow.ComponentMetaDataCollection)
{
// Get the inputs in the component.
foreach (IDTSInput100 currentInput in currentComponent.InputCollection)
foreach (IDTSInputColumn100 currentInputColumn in currentInput.InputColumnCollection)
lineageIds.Add(currentInputColumn.ID, currentInputColumn.Name);
// Get the outputs in the component.
foreach (IDTSOutput100 currentOutput in currentComponent.OutputCollection)
foreach (IDTSOutputColumn100 currentoutputColumn in currentOutput.OutputColumnCollection)
lineageIds.Add(currentoutputColumn.ID, currentoutputColumn.Name);
}
}
4。在数据流中创建脚本组件,只读访问lineageIds
和以下代码。
public override void Input0_ProcessInputRow(Input0Buffer Row)
{
Dictionary<int, string> lineageIds = (Dictionary<int, string>)Variables.lineageIds;
int? colNum = Row.ErrorColumn;
if (colNum.HasValue && (lineageIds != null))
{
if (lineageIds.ContainsKey(colNum.Value))
Row.ErrorColumnName = lineageIds[colNum.Value];
else
Row.ErrorColumnName = "Row error";
}
Row.ErrorDescription = this.ComponentMetaData.GetErrorDescription(Row.ErrorCode);
}
答案 2 :(得分:1)
右键单击CSV组件(以及许多其他组件),然后选择“显示高级编辑器”。转到最后一个选项卡“输入和输出属性”
在此屏幕上,在树状菜单中查看输出列(NOT(!)外部列)。它们在“公共属性”中具有谱系id
有很多jabber很难找到,没有重新编写视觉工作室本身的代码就不可能找到什么但是我只是在2010年和2012年在不同的系统上检查了这一点并且它不是更难然后我刚刚描述的内容。