2017-02-25 321 views
1

我目前正在創建一個SSIS,它將從數據庫收集數據並將其輸出到單個逗號分隔的平面文件。該文件將包含訂單明細文件格式爲SSIS - 輸出到平面文件的各種列數

Order#1 details (51 columns) 
Order#1 header (62 columns) 
Order#2 details (51 columns) 
Order#2 header (62 columns) 
etc... 

訂單標題有62列,訂單明細有51列。我需要輸出到一個平面文件,我遇到了一個問題,因爲SSIS不處理不同的列。有人可以幫助我,並且由於我的源代碼是查詢中的OLEDB源,我如何創建腳本組件以輸出到文件。

電流封裝如下所示:

  1. 獲取所有命令的列表。將orderid作爲變量傳遞。
  2. For循環容器通過每個orderid,運行數據任務流以獲取訂單的訂單詳細信息。運行數據任務以獲取訂單標題。 我只是遇到一個問題,輸出每一行到平面文件。

如果任何人都可以幫助,將非常感激。我一直在努力爭取一週的時間。如果任何人都可以從腳本組件代碼的外觀開始,我會非常感激。

我已經加入了我到目前爲止有: http://imgur.com/a/yTxfH

這是我的腳本是什麼樣子:

public void Main() 
    { 
     // TODO: Add your code here 
     DataTable RecordType300 = new DataTable(); 
     DataTable RecordType210 = new DataTable(); 
     DataTable RecordType220 = new DataTable(); 
     DataTable RecordType200 = new DataTable(); 

     OleDbDataAdapter adapter = new OleDbDataAdapter(); 
     adapter.Fill(RecordType300, Dts.Variables["User:rec_type300"].Value); 
     adapter.Fill(RecordType210, Dts.Variables["User::rec_type_210"].Value); 
     adapter.Fill(RecordType220, Dts.Variables["User::rec_type_220"].Value); 
     adapter.Fill(RecordType200, Dts.Variables["User::rec_type200"].Value); 
     using (StreamWriter outfile = new StreamWriter("C:\\myoutput.csv")) 
     { 
      for (var i = 0; i < RecordType300.Rows.Count; i++) 
      { 
       var detailFields = RecordType300.Rows[i].ItemArray.Select(field => field.ToString()).ToArray(); 
       // var poBillFields = RecordType210.Rows[i].ItemArray.Select(field => field.ToString()).ToArray(); 
       // var poShipFields = RecordType220.Rows[i].ItemArray.Select(field => field.ToString()).ToArray(); 
      // var poHeaderFields = RecordType200.Rows[i].ItemArray.Select(field => field.ToString()).ToArray(); 
       outfile.WriteLine(String.Join(",", detailFields)); 
       // outfile.WriteLine(string.Join(",", poBillFields)); 
       // outfile.WriteLine(string.Join(",", poShipFields)); 
       // outfile.WriteLine(string.Join(",", poHeaderFields)); 
      } 
     } 

     Dts.TaskResult = (int)ScriptResults.Success; 

    } 

但每次我運行它,它的錯誤了時間。我在這裏錯過了什麼嗎?另外,我將如何在一開始只創建一個文件。這意味着每次運行這個軟件包時,它都會創建一個帶有日期戳記的文件並且每次都附加到它。下次運行包時,它將創建一個新文件,並帶有新的日期戳,並根據訂單號附加每個訂單詳細信息。

+0

我認爲你是在正確的軌道與腳本的想法。考慮將標題和細節的結果放入兩個單獨的DataTable中。看看這個鏈接是一個如何填充和遍歷它們的例子。 http://stackoverflow.com/a/14103080 – sorrell

+0

@Sorrell。目前我有兩個獨立的數據表。我遇到的問題實際上是創建腳本。 – a415

+1

破碎文件的常用解決方法是將數據導出爲_one_列,該列恰好包含一組逗號分隔的數據。您可以編寫一個查詢來生成和導出,但這取決於您是否更喜歡T-SQL或C#。恕我直言,C#/ Lookup方法令人費解並且斷開連接。我更喜歡編寫一個SQL查詢來完成所有工作(高效)並將其導出 –

回答

1

這個代碼/方法還沒有經過測試,但應該給你一個好辦法。

  1. 創建2個對象類型的SSIS變量,一個用於標題,一個用於細節。Variables
  2. 創建2個Execute SQL任務和1 Script Task如下概括:Overview
  3. 設置你的任務來處理一個完整的結果集,類似於這些照片(的詳細版本號顯示,做頭,但地圖結果頁眉相似對象,並在頭表改變你的查詢點):現在ReadOnlyVars
  4. 編輯您的實際腳本沿着這些線路(這是假設你有:ExecSqlExecSql2
  5. 編輯腳本任務,並允許DetailHeader爲只讀瓦爾究竟1個標題行1個詳細信息行):

using System.IO; 
using System.Linq; 
using System.Data.OleDb; 

// following to be inserted into Main() function 
DataTable detailData = new DataTable(); 
DataTable headerData = new DataTable(); 
OleDbDataAdapter adapter = new OleDbDataAdapter(); 
adapter.Fill(detailData, Dts.Variables["User::Detail"].Value); 
adapter.Fill(headerData, Dts.Variables["User::Header"].Value); 

using (StreamWriter outfile = new StreamWriter("myoutput.csv")) 
{ 
    // we are making the assumption that 
    for (var i = 0; i < detailData.Rows.Count; i++) 
    { 
     var detailFields = detailData.Rows[i].ItemArray.Select(field => field.ToString()).ToArray(); 
     var headerFields = headerData.Rows[i].ItemArray.Select(field => field.ToString()).ToArray(); 
     outfile.WriteLine(string.Join(",", detailFields)); 
     outfile.WriteLine(string.Join(",", headerFields)); 
    } 
} 
+0

謝謝。這真的很棒。但是,我不想從腳本中提取數據,因爲我必須執行其他查找操作。例如,在輸出之前,我必須對公司名稱進行查找。 – a415

+0

如果我有它執行SQL任務腳本,那麼我將無法對列進行更改。 – a415

+1

您可以在數據流中執行的任何操作都可以使用SQL和C#完成。例如,您可以重新構建查詢以加入公司表來獲取名稱,而不是查找?如果是這樣,那麼這一列就是你的結果集的一部分。派生和計算也可以使用SQL和/或C#完成。 – sorrell

1

不是一個完整的答案,只是一些把你的替代方法

SELECT Type, OrderBy, Col 
FROM 
(
    SELECT 'D' As Type, Ord as OrderBy, 
    Col1 + ',' + CAST(Col2 AS VARCHAR(50)) + ',' + Col3 As Col 
    FROM Details 
    UNION ALL 
    SELECT 'H' As Type, Ord as OrderBy, 
    Col1 + ',' + CAST(Col2 AS VARCHAR(50)) + ',' + Col3 As Col + ',' + Col4 
    FROM Header 
) S 
ORDER BY OrderBy, Type 

的軌道上它的醜陋,但它工作,只要你把所有的數據類型varchar

您可以將其封裝在視圖或存儲過程中,並從數據庫中進行測試(在訪問SSIS部件之前)。你甚至可以導出此使用BCP.EXE而不是SSIS

你這裏是什麼一列恰好包含此類型的數據:

A,B,C 
D,E,F,G 

從元數據角度來看,始終是一列

從CSV的角度來看,有可變的列