web-dev-qa-db-ja.com

SSIS-パスファイル名文字列から拡張子を解析する方法

CSVからファイルデータの大規模なセット(126M行)をインポートしています。インポートは正常に機能しますが、インポート時に列を導出しようとしているのですが(行数が多いため)後でスクリプトを実行するのではありません。 SSISは文字列操作関数にはそれほど役立ちませんし、私が持っている可能性もかなり複雑です。

派生列は、ファイル拡張子を反映する必要があります。ファイル拡張子の範囲は1〜10文字(10で切り捨てることができます)で、(もちろん)ファイル名とパスからピリオドで区切られます。それらは、ファイルタイプの簡潔なリストに対応していません(「docx、xlsx、accdb、msg」などはOfficeタイプです)。ファイルパスにもピリオドが含まれている場合があります。また、場合によっては、パスの最後にファイルがなく、フォルダ名自体が含まれることもあります。いくつかの例:

\\Server\Share\named resource
\\Server\Share\this.looks.like.a.file_but.it.isnt\its_a_directory
\\Server\Share\Group\Year.Month.Day.Subfolder\File.ext
\\Server\Share\Team Folder 1.404\another.file.here.extension

したがって、最大10文字の拡張子を抽出できる必要があります。私はTOKEN()を試しましたが、フォルダ名にピリオドが含まれている可能性があるため、うまくいきませんでした-\トークン区切り文字としていくつかは役に立ちましたが、それでもフォルダ名から奇妙な拡張子を得ました。ルールを満たすSUBSTRING()、RIGHT()、FINDSTRING()、および/またはTOKEN()の組み合わせが見つからず、派生列の定義でIFやIIFなどのロジックが許可されていません。

いくつかの誤検知が予想され、インポート後にそれらを整理する予定です。ここで役立つ場合は、SSISによって抽出されたCSVに2番目の列があります。これはファイルのサイズです(フォルダーの場合は0が入力されます)。派生列の定義にIFまたはIIFがないため、これも問題になりませんでした。

3
Fred Shope

まず、探しているIF/IIFは「?」です。条件付き演算子

?条件付き

派生列を実装する1つの方法は、次のように文字列を解析することです。

_ TOKENCOUNT( TOKEN( REVERSE( RTRIM( name ) ), "\\", 1), "." ) == 1
 ? "" : REVERSE( TOKEN( TOKEN( REVERSE( RTRIM( name ) ), "\\", 1), ".", 1) )
_

この場合、「name」は解析される文字列を保持する列です。

ここで行っていることは次のとおりです。

  1. RTRIM( name )で末尾の空白を削除します
  2. 文字列を逆にして、REVERSE()で始まりを終わりとして扱うようにします
  3. TOKEN()を使用して、バックスラッシュで区切られた最初の「トークン」を取得します
  4. 「。」の数を数えます。区切り文字はTOKENCOUNT()を使用して結果に含まれます
  5. 「。」の数をテストします。区切りトークンは、_?_を使用して1に等しい
  6. カウントが1の場合、空の文字列-拡張子なしを返します。
  7. それ以外の場合は、「。」の前の最初のトークンを返します。 TOKEN()を使用する
  8. REVERSE()を使用して拡張機能を元に戻し、「通常」に戻します
2
Mister Magoo

これは式言語(T-SQL)にはありませんが、これをパターンとして使用したり、SQLからデータをプルしたりできる場合(それがある場合)。

CREATE TABLE #test (Col1 varchar(100))

INSERT INTO #test VALUES 
    ('\\Server\Share\named resource'),
    ('\\Server\Share\this.looks.like.a.file_but.it.isnt\its_a_directory'),
    ('\\Server\Share\Group\Year.Month.Day.Subfolder\File.ext'),
    ('\\Server\Share\Team Folder 1.404\another.file.here.extension')

SELECT CASE WHEN CHARINDEX('.',REVERSE(Ending)) > 0 THEN 
    RIGHT(Ending,CHARINDEX('.',REVERSE(Ending))-1) ELSE '' END
FROM #test
CROSS APPLY (VALUES  (RIGHT(Col1,CHARINDEX('\',REVERSE(Col1))-1))) x(Ending)

これをパターンとして使用している場合は、endingの派生列を作成し、残りをその列に適用できます。本当に1つのパスでそれを行うことができますが、その方法ははるかに複雑です。

1
Kenneth Fisher