使用指令碼元件建立同步轉換
您會在 Integration Services 封裝的資料流程中使用轉換元件,以修改和分析從來源傳遞到目的地的資料具有同步輸出的轉換會處理通過該元件的每個輸入資料列。具有非同步輸出的轉換會等到它收到所有的輸入資料列後,才完成其處理。本主題討論同步轉換。如需有關非同步轉換的詳細資訊,請參閱<使用指令碼元件建立非同步轉換>。如需有關同步和非同步元件之間差異的詳細資訊,請參閱<了解同步和非同步轉換>。
如需指令碼元件的概觀,請參閱<以指令碼元件擴充資料流程>。
指令碼元件以及它為您產生的基礎結構程式碼,可大幅簡化開發自訂資料流程元件的程序。不過,若要了解指令碼元件如何運作,閱讀<開發自訂資料流程元件>一節中有關開發自訂資料流程元件所必須遵循的步驟,以及特別是<開發具有同步輸出的自訂轉換元件>,可能會非常有幫助。
開始使用同步轉換元件
當您將指令碼元件加入 SSIS 設計師的 [資料流程] 窗格時,就會開啟 [選取指令碼元件類型] 對話方塊,並提示您選取 [來源]、[目的地] 或是 [轉換] 元件類型。在這個對話方塊中,選取 [轉換]。
在中繼資料設計模式中設定同步轉換元件
在您選取可建立轉換元件的選項之後,請藉由使用 [指令碼轉換編輯器] 來設定元件。如需詳細資訊,請參閱<在指令碼元件編輯器中設定指令碼元件>。
若要設定指令碼元件的指令碼語言,請在 [指令碼轉換編輯器] 中,設定 [指令碼] 頁面上的 ScriptLanguage 屬性。
[!附註]
若要為指令碼元件設定預設的指令碼語言,請使用 [選項] 對話方塊中 [一般] 頁面上的 [指令碼語言] 選項。如需詳細資訊,請參閱<一般頁面>。
資料流程轉換元件有一個輸入,而且支援一或多個輸出。設定元件的輸入與輸出是您必須在中繼資料設計模式下完成的其中一個步驟,方法是在撰寫自訂指令碼之前先使用 [指令碼轉換編輯器]。
設定輸入資料行
轉換元件有一個輸入。
在 [指令碼轉換編輯器] 的 [輸入資料行] 頁面上,資料行清單會從資料流程中的上游元件輸出顯示可用的資料行。選取要轉換或通過的資料行。將任何您要就地轉換的資料行標示成「讀取/寫入」。
如需有關 [指令碼轉換編輯器] 的 [輸入資料行] 頁面的詳細資訊,請參閱<指令碼轉換編輯器 (輸入資料行頁面)>。
設定輸入、輸出及輸出資料行
轉換元件支援一或多個輸出。
在 [指令碼轉換編輯器] 的 [輸入及輸出] 頁面上,您可以看到已建立單一輸出,但是輸出沒有資料行。在編輯器的此頁面上,您可能會需要或想要設定下列項目。
建立一或多個其他輸出,例如含有非預期值的資料列之模擬錯誤輸出。使用 [加入輸出] 和 [移除輸出] 按鈕管理同步轉換元件的輸出。所有的輸入資料列都會導向至所有可用的輸出,除非您指定想要將每個資料列重新導向至某個輸出或是另一個輸出。您為輸出上的 ExclusionGroup 屬性指定非零的整數值,以指出想要重新導向資料列。在 ExclusionGroup 中輸入哪一個特定整數值來識別輸出並不重要,但是您必須為指定的輸出群組持續地使用相同的整數。
[!附註]
當您不想要輸出所有的資料列時,也可以使用具有單一輸出的非零 ExclusionGroup 屬性值。然而,在此情況下,您必須為要傳送至輸出的每個資料列,明確地呼叫 DirectRowTo<outputbuffer> 方法。
指派更具描述性的名稱給輸入與輸出。指令碼元件使用這些名稱來產生具類型的存取子屬性,您將使用這些屬性來參考指令碼中的輸入和輸出。
保留資料行的原狀以進行同步轉換。一般而言,同步轉換不會將資料行加入資料流程。資料會在緩衝區中就地修改,而緩衝區則會傳遞至資料流程中的下一個元件。如果是這樣的情況,您不必在轉換的輸出上明確地加入和設定輸出資料行。輸出會出現在編輯器中,但沒有任何明確定義的資料行。
將新資料行加入資料列層級錯誤的模擬錯誤輸出。通常在相同 ExclusionGroup 中的多個輸出都有相同的一組輸出資料行。然而,如果您正在建立模擬的錯誤輸出,可能會想要加入更多的資料行以包含錯誤資訊。如需有關資料流程引擎如何處理錯誤資料列的詳細資訊,請參閱<使用資料流程元件中的錯誤輸出>。不過,在指令碼元件中,您必須撰寫自已的程式碼,以適當的錯誤資訊填寫其他資料行。如需詳細資訊,請參閱<模擬指令碼元件的錯誤輸出>。
如需有關 [指令碼轉換編輯器] 的 [輸入及輸出] 頁面的詳細資訊,請參閱<指令碼轉換編輯器 (輸入及輸出頁面)>。
加入變數
如果您想要在指令碼中使用現有的變數,可以在 [指令碼轉換編輯器] 的 [指令碼] 頁面上,將它們加入 ReadOnlyVariables 與 ReadWriteVariables 屬性欄位中。
當您在屬性欄位中加入多個變數時,請用逗號分隔變數名稱。您也可以按一下 ReadOnlyVariables 與 ReadWriteVariables 屬性欄位旁邊的省略符號 (…) 按鈕,然後選取 [選取變數] 對話方塊中的變數,來選取多個變數。
如需有關如何透過指令碼元件使用變數的一般資訊,請參閱<在指令碼元件中使用變數>。
如需有關 [指令碼轉換編輯器] 的 [指令碼] 頁面的詳細資訊,請參閱<指令碼轉換編輯器 (指令碼頁面)>。
在程式碼設計模式中編寫同步轉換元件的指令碼
在您設定好元件的中繼資料之後,便可撰寫自訂指令碼。在 [指令碼轉換編輯器] 的 [指令碼] 頁面上,按一下 [編輯指令碼],開啟 MicrosoftVisual Studio Tools for Applications (VSTA) IDE 以加入自訂指令碼。所使用的指令碼語言,取決於您是選取 MicrosoftVisual Basic 2008 或 MicrosoftVisual C# 2008 做為 [指令碼] 頁面上 ScriptLanguage 屬性的指令碼語言而定。
如需使用指令碼元件所建立之各種元件都適用的重要資訊,請參閱<指令碼元件的程式碼撰寫和偵錯>。
了解自動產生的程式碼
當您在建立和設定轉換元件之後開啟 VSTA IDE,可編輯的 ScriptMain 類別會出現在程式碼編輯器中,並具有 ProcessInputRow 方法的 Stub。ScriptMain 類別是您將撰寫自訂程式碼的地方,而 ProcessInputRow 則是轉換元件中最重要的方法。
如果您在 VSTA 中開啟 [專案總管] 視窗,可以看到指令碼元件也會產生唯讀的 BufferWrapper 與 ComponentWrapper 專案項目。ScriptMain 類別會繼承 ComponentWrapper 專案項目中的 UserComponent 類別。
在執行階段,資料流程引擎會叫用 UserComponent 類別中的 ProcessInput 方法,它會覆寫 ScriptComponent 父類別的 ProcessInput 方法。ProcessInput 方法接著會在輸入緩衝區的資料列中執行迴圈,並為每個資料列呼叫一次 ProcessInputRow 方法。
撰寫您的自訂程式碼
具有同步輸出的轉換元件是所有資料流程元件中最容易撰寫的。例如,在本主題稍後所顯示的單一輸出範例是由下列自訂程式碼所組成:
Row.City = UCase(Row.City)
Row.City = (Row.City).ToUpper();
若要完成建立自訂同步轉換元件,可以使用覆寫的 ProcessInputRow 方法,轉換輸入緩衝區之每個資料列中的資料。資料流程引擎會在變滿時將這個緩衝區傳遞到資料流程中的下一個元件。
視您的需求而定,您也可能會想要在 PreExecute 與 PostExecute 方法 (可在 ScriptMain 類別中取得) 中撰寫指令碼,以執行初步或是最後的處理。
使用多個輸出
相較於之前討論的單一輸出狀況,將輸入資料列導向兩個或更多可能的輸出之一,並不需要更多的自訂程式碼。例如,在本主題稍後所顯示的雙輸出範例是由下列自訂程式碼所組成:
[Visual Basic]
Row.City = UCase(Row.City)
If Row.City = "REDMOND" Then
Row.DirectRowToMyRedmondAddresses()
Else
Row.DirectRowToMyOtherAddresses()
End If
[C#]
Row.City = (Row.City).ToUpper();
if (Row.City=="REDMOND")
{
Row.DirectRowToMyRedmondAddresses();
}
else
{
Row.DirectRowToMyOtherAddresses();
}
在這個範例中,根據您所設定的輸出名稱而定,指令碼元件會為您產生 DirectRowTo<OutputBufferX> 方法。您可以使用類似的程式碼將錯誤資料列導向模擬的錯誤輸出。
範例
以下範例示範在 ScriptMain 類別中所需的自訂程式碼,以建立同步轉換元件。
[!附註]
這些範例使用 AdventureWorks 範例資料庫中的 Person.Address 資料表,並透過資料流程傳遞其第一個和第四個資料行:intAddressID 和 nvarchar(30)City 資料行。在本章節中的來源、轉換和目的地範例使用相同的資料。每個範例都會記載其他必要條件與假設。
單一輸出同步轉換範例
此範例示範具有單一輸出的同步轉換元件。此轉換會通過 AddressID 資料行,並將 City 資料行轉換為大寫字元。
如果您要執行這個範例程式碼,必須依下列方式設定封裝與元件:
將新指令碼元件加入資料流程設計師介面,並將它設定為轉換。
將來源的輸出或另一個轉換的輸出連接到 SSIS 設計師中的新轉換元件。這個輸出應該從 AdventureWorks 範例資料庫的 Person.Address 資料表中提供資料,這個資料表包含 AddressID 與 City 資料行。
開啟 [指令碼轉換編輯器]。在 [輸入資料行] 頁面,選取 AddressID 與 City 資料行。將 City 資料行標示為讀取/寫入。
在 [輸入及輸出] 頁面上,以更具描述性的名稱重新命名輸入與輸出,例如 MyAddressInput 與 MyAddressOutput。請注意,輸出的 SynchronousInputID 會對應至輸入的 ID。因此,您不必加入和設定輸出資料行。
在 [指令碼] 頁面上,按一下 [編輯指令碼] 並輸入以下指令碼。然後關閉指令碼開發環境以及 [指令碼轉換編輯器]。
建立和設定需要 AddressID 與 City 資料行的目的地元件 (例如 SQL Server 目的地),或是在使用指令碼元件來建立目的地中所示範的範例目的地元件。然後將轉換的輸出連接到目的地元件。您可以在 AdventureWorks 資料庫中執行下列 Transact-SQL 命令,以建立目的地資料表:
CREATE TABLE [Person].[Address2]( [AddressID] [int] NOT NULL, [City] [nvarchar](30) NOT NULL )
執行範例。
Public Class ScriptMain
Inherits UserComponent
Public Overrides Sub MyAddressInput_ProcessInputRow(ByVal Row As MyAddressInputBuffer)
Row.City = UCase(Row.City)
End Sub
End Class
[C#]
public class ScriptMain:
UserComponent
{
public override void MyAddressInput_ProcessInputRow(MyAddressInputBuffer Row)
{
Row.City = (Row.City).ToUpper();
}
}
雙輸出同步轉換範例
此範例示範具有兩個輸出的同步轉換元件。此轉換會通過 AddressID 資料行,並將 City 資料行轉換為大寫字元。如果城市名稱是 Redmond,它會將資料列導向其中一個輸出,並將所有的其他資料列導向另一個輸出。
如果您要執行這個範例程式碼,必須依下列方式設定封裝與元件:
將新指令碼元件加入資料流程設計師介面,並將它設定為轉換。
將來源的輸出或另一個轉換的輸出連接到 SSIS 設計師中的新轉換元件。這個輸出應該從 AdventureWorks 範例資料庫的 Person.Address 資料表中提供資料,這個資料表至少包含 AddressID 與 City 資料行。
開啟 [指令碼轉換編輯器]。在 [輸入資料行] 頁面,選取 AddressID 與 City 資料行。將 City 資料行標示為讀取/寫入。
在 [輸入及輸出] 頁面上,建立第二個輸出。在加入新輸出之後,請確定將其 SynchronousInputID 設定為輸入的 ID。在預設會建立的第一個輸出上已經設定這個屬性。對於每個輸出,請將 ExclusionGroup 屬性設定為相同的非零值,以指出您將在兩個互斥輸出之間分割輸入資料列。您不必將任何輸出資料行加入輸出。
使用更具描述性的名稱重新命名輸入與輸出,例如 MyAddressInput、MyRedmondAddresses 與 MyOtherAddresses。
在 [指令碼] 頁面上,按一下 [編輯指令碼] 並輸入以下指令碼。然後關閉指令碼開發環境以及 [指令碼轉換編輯器]。
建立和設定兩個需要 AddressID 與 City 資料行的目的地元件,例如 SQL Server 目的地、一般檔案目的地,或是在使用指令碼元件來建立目的地中所示範的範例目的地元件。然後將每個轉換輸出連接到其中一個目的地元件。您可以在 AdventureWorks 資料庫中執行類似下列程式碼 (具有唯一的資料表名稱) 的 Transact-SQL 命令,以建立目的地資料表:
CREATE TABLE [Person].[Address2]( [AddressID] [int] NOT NULL, [City] [nvarchar](30) NOT NULL
執行範例。
Public Class ScriptMain
Inherits UserComponent
Public Overrides Sub MyAddressInput_ProcessInputRow(ByVal Row As MyAddressInputBuffer)
Row.City = UCase(Row.City)
If Row.City = "REDMOND" Then
Row.DirectRowToMyRedmondAddresses()
Else
Row.DirectRowToMyOtherAddresses()
End If
End Sub
End Class
public class ScriptMain:
UserComponent
public override void MyAddressInput_ProcessInputRow(MyAddressInputBuffer Row)
{
Row.City = (Row.City).ToUpper();
if (Row.City == "REDMOND")
{
Row.DirectRowToMyRedmondAddresses();
}
else
{
Row.DirectRowToMyOtherAddresses();
}
}
}
|