開篇介紹
上午在天善回答看到這個問題 - SSIS 導出數據文件,能否在第一列增加一個行號,很快就幫助解決了,方法就是在 SQL 查詢的時候加一個 ROW_NUMBER() 就可以了。
后來想起在兩年前我的第一個 BI 項目上也有類似的文件輸出需求,但是比這個要復雜的多,因為涉及到多個輸入列的邏輯判斷和計算問題,比如還有一些 XML 格式的數據。這些邏輯不能直接在 SQL 查詢時直接實現,比如還要做 XML 格式驗證,字符串匹配查找,還有其它的比較復雜的邏輯。所以就選擇了另外一種方式 - 在數據源輸入和文件輸出組件之間加了一個 Script Component 組件,利用它程序化處理添加了必要的輸出列供下游使用,當然邏輯比較復雜在 Script Component 中寫了不少代碼還有異常記錄輸出等。
雖然沒有必要使用 Script Component 來解決這個問題,但是還是可以通過這個小例子簡單介紹一下 Script Component,多了解一種方法,在項目需要的時候就多一種選擇。
使用 Script Component 為數據流輸出添加行號
數據源可以隨便選用一張表來進行測試輸出。
數據源向下的輸出列 -
拖放一個排序控件,如果希望輸出的格式按某列排序的話,可以選擇一個列來排序,這里使用 FullName 進行排序。
拖放一個 Script Component,這里要選擇 Transfomation 轉換,意味着在輸入源和輸出目的地之間進行中間轉換的組件。
如果以后在 Script 中有比較復雜的邏輯運算需要使用到輸入源的某些列的話,可以在這里選中它。
最重要的就是這里的輸出列了,這個輸出列之前並不存在,是通過 Script Component 創建出來的,后面可以使用到的。
選擇 Script 項並點擊 Edit Script 打開之后就能看到這些代碼,這里面有幾個方法。
- PreExecute() - 只會被調用一次,在數據流執行到這個控件的時候調用,並且是在所有行處理前調用,可以在這里做一些初始化計算。
- PostExecute() - 當所有行全部處理完之后調用,可以在這里和 PreExecute() 配合起來記錄處理的時間,時長等等。
/// <summary> /// This method is called once, before rows begin to be processed in the data flow. /// /// You can remove this method if you don't need to do anything here. /// </summary> public override void PreExecute() { base.PreExecute(); /* * Add your code here */ } /// <summary> /// This method is called after all the rows have passed through this component. /// /// You can delete this method if you don't need to do anything here. /// </summary> public override void PostExecute() { base.PostExecute(); /* * Add your code here */ } /// <summary> /// This method is called once for every row that passes through the component from Input0. /// /// Example of reading a value from a column in the the row: /// string zipCode = Row.ZipCode /// /// Example of writing a value to a column in the row: /// Row.ZipCode = zipCode /// </summary> /// <param name="Row">The row that is currently passing through the component</param> public override void Input0_ProcessInputRow(Input0Buffer Row) { /* * Add your code here */ }
最后的一個方法是我們要使用到的,就是轉換處理。在方法外面定義一個變量,表示行號從 1 開始。方法參數 Row 已經將之前在 Script Component 中引用的 InputColumn 和 創建的 OutputColumn 全部包裝成了屬性,直接可以通過 Input0Buffer Row 來調用。 那么每進來一行數據,這個方法就被調用一次並同時向下輸出一次。也就是說進來一行,處理一行,出去一行。
int rowNumber = 1; public override void Input0_ProcessInputRow(Input0Buffer Row) { Row.RowNumber = rowNumber; rowNumber = rowNumber + 1; }
保存並執行包,開啟一個 Data Viewer 查看一下運行時的數據,就能看到 RowNumber 已經創建好了,下游就可以向文件寫入數據了。
使用 ROW_NUMBER()來實現添加數據流的行號
當然對於這個例子,直接使用 ROW_NUMBER() 最簡單了,維護成本很低。
一步就搞定了同樣的效果。
更多 BI 文章請參看 BI 系列隨筆列表 (SSIS, SSRS, SSAS, MDX, SQL Server) 如果覺得這篇文章看了對您有幫助,請幫助推薦,以方便他人在 BIWORK 博客推薦欄中快速看到這些文章。