34

行をフラット ファイル ソースからフラット ファイル宛先にリダイレクトしています。リダイレクトされた行のデフォルトのメタデータは次のとおりです。

  • 元のフラット ファイル ソース行
  • エラーコード
  • エラー列

出力フラット ファイルで得られるのは、ソース行 (適切) とエラー コード (不適切、例: -1071628249)、およびエラー列 (列の内部 ID であるため不適切) です。

行を変換して、エラー メッセージ (「データが切り捨てられました」など) とフラット ファイル ソースで定義されている列名を出力するにはどうすればよいですか?

言い換えれば、...,-1071607675,10私が見たいのではなく:

...,The data was truncated,Firstname

または代わりに (前の方法が不可能な場合);

...,DTS_E_FLATFILESOURCEADAPTERSTATIC_TRUNCATED,Firstname.

4

10 に答える 10

15

質問の一部 (エラーの説明の追加) は、スクリプト コンポーネントを使用して実現できます。これについては、スクリプト コンポーネントを使用したエラー出力の拡張で説明されています。

Dougbertブログには、列名を追加するための解決策があるようですが、単純ではありません。SSIS でこれを行うのが非常に難しいことに驚いています。ソースと列の名前を知ることは基本的な必要性だと思うでしょう。

于 2012-10-03T08:59:48.660 に答える
5

Pragmatic Works には、 "Task Factory" と呼ばれる製品のCommunity Edition (無料)の一部であるError Output Description Transformがあるようです。

Error Output Description Transform は、ErrorCode、ErrorColumn、ErrorDescription、ComponentName (エラーを生成した)、ColumnName (既知の場合)、ColumnType、および ColumnLength などの貴重な情報を取得できるユーザー インターフェイスをユーザーに提供します。

また、任意の入力列をエラー出力に渡すこともできます。正直なところ、非常に便利で、SSIS パッケージのトラブルシューティングに何時間も費やすことができました。

于 2013-06-03T19:37:15.973 に答える
2
    //column error description 
    Row.ErrorDescription = this.ComponentMetaData.GetErrorDescription(Row.ErrorCode);

    //we are getting column name with some extra information
    String rawColumnName = this.ComponentMetaData.GetIdentificationStringByLineageID(Row.ErrorColumn);

    //extracting positions of brackets 
    int bracketPos = rawColumnName.LastIndexOf('[')+1;
    int lastBracketPos = rawColumnName.LastIndexOf(']');

    //extracting column name from the raw column name
    Row.ErrorColName = rawColumnName.Substring(bracketPos, (lastBracketPos - bracketPos));
于 2016-02-29T13:14:29.157 に答える
1

これが解決策です

  1. パッケージの実行時に動作します (事前設定ではありません)。
  2. スクリプト タスクとコンポーネントによって自動化されている
  3. 新しいアセンブリやカスタム コンポーネントをインストールする必要はありません
  4. BIMLとうまく互換性があります

ここで完全なソリューションを確認してください。


こちらがショートバージョンです。

  1. 2 つのオブジェクト変数を作成execsObjし、lineageIds
  2. 制御フローでスクリプト タスクを作成し、両方の変数への読み取り/書き込みアクセスを許可します。
  3. 次のコードをスクリプト タスクに挿入します。
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);
    }
}

lineageIds4.次のコードへの読み取り専用アクセス権を持つスクリプト コンポーネントをデータフローに作成します。

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);
  }
于 2015-10-31T02:30:03.090 に答える