Sql-Server
當每個季度的列不一致時,使用 SSIS 將 csv 文件導入 SQL Server 時出現問題
我正在使用 SSIS 將一堆 csv 表上傳到 SQL Server Express。csv 文件是季度數據文件。它們在很大程度上是一致的,但每隔幾年可能會添加一列或刪除現有的列。
每次 SSIS 在出現的列中遇到更改時,它都會引發以下一個或兩個錯誤:
錯誤:數據流任務中的 0xC0202055,平面文件源
$$ 2 $$: 未找到列“XYZ”的列分隔符。 錯誤:數據流任務中的 0xC0202091,平面文件源
$$ 2 $$: 跳過數據行時出錯。
添加新列時,會出現兩個錯誤。排除現有列時,僅出現 2091 錯誤。請注意,這些列在被刪除時不僅為空,它們不再存在於數據中。
是否有設置或我可以使用的東西,以便 SSIS 適應列中的這些更改?我嘗試使用完整的列集設置目標表,但這沒有幫助。
謝謝,
您可以使用腳本轉換來創建實際的列映射。對於您的平面文件源,使每個輸出行都成為一個大列。
在您的腳本轉換中,為您需要映射/已經知道的每一列創建列定義。
這假設您的第一行包含標題:
然後,在您的腳本轉換中,按您需要的分隔符分割每一行。您可以創建一個布爾值來指示第一行是否已被讀取。如果不是,則解析該行並將列映射位置儲存在 Dictionary<string,int> 中,例如 ColumnMappings,並且不要寫入 OutputBuffer。如果您的行閱讀器看到列映射已被讀取,那麼您可以將輸出設置為正確的列,例如:
OutputBuffer.MyMappedColumn = SplitRow[ColumnMappings["MyMappedColumn"]];
下面是帶有“Day”列的整個轉換的範例
using System; using System.Data; using System.Text; using Microsoft.SqlServer.Dts.Pipeline.Wrapper; using Microsoft.SqlServer.Dts.Runtime.Wrapper; [Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute] public class ScriptMain : UserComponent { UTF8Encoding enc = new UTF8Encoding(); char[] separator = { ',' }; bool _isColumnMappingComplete = false; System.Collections.Generic.Dictionary<string, int> _columnMapping; bool isWritable = false; bool isColumnMappingComplete { //Set true after first row processed get{ return _isColumnMappingComplete; } set{ _isColumnMappingComplete = value;} } System.Collections.Generic.Dictionary<string, int> columnMapping{ //Object to hold column mapping indexes get { if (_columnMapping == null) { _columnMapping = new System.Collections.Generic.Dictionary<string, int>(); } return _columnMapping; } set { _columnMapping = value; isColumnMappingComplete = true; } } public override void PreExecute() { base.PreExecute(); /* Add your code here for preprocessing or remove if not needed */ } public override void PostExecute() { isWritable = true; base.PostExecute(); /* Add your code here for postprocessing or remove if not needed You can set read/write variables here, for example: Variables.MyIntVar = 100 */ } public override void Input0_ProcessInputRow(Input0Buffer Row) { bool isEmptyRow = false; //byte[] rawRowBytes = Row.Column0.GetBlobData(0,(int)Row.Column0.Length); //uncomment if using Text input datatype //string rawRow = enc.GetString(rawRowBytes); //uncomment if using Text input datatype string rawRow = Row.Column0; //comment out if using Text input datatype if (rawRow.Replace("\"", "").Replace(",", "").Replace(" ", "").Length == 0) { isEmptyRow = true; } if (!isEmptyRow) { string[] rowData = rawRow.Split(separator); if (!isColumnMappingComplete) { System.Collections.Generic.Dictionary<string, int> firstColMap = new System.Collections.Generic.Dictionary<string, int>(); for (int i = 0; i < rowData.Length; i++) { firstColMap.Add(rowData[i], i); } columnMapping = firstColMap; } else { Output0Buffer.AddRow(); bool _rowError = false; //Day if (columnMapping.ContainsKey("Day")) { Output0Buffer.Day = rowData[columnMapping["Day"]]; } else { //Output0Buffer.Day = "-"; _rowError = true; } } } } public override void CreateNewOutputRows() { /* Add rows by calling the AddRow method on the member variable named "<Output Name>Buffer". * For example, call MyOutputBuffer.AddRow() if your output was named "MyOutput". */ } }
處理 SSIS 時無法動態調整。您將需要“使它們像上次一樣一致”或更改您的載入過程。目標表可以輕鬆調整,調整 txt 或 csv 文件連接器可能會更成問題。
如果可能的話,我希望從創建報告的查詢中提取數據。從長遠來看,這將最大限度地減少您的更改。