從SQL Server中的儲存過程執行SSIS包
問題
我們的組織一直在使用SSIS包來執行與後端資料庫直接相關的各種操作。我們希望能夠直接從我們的應用程式中利用這些功能。通常,我們構建SSIS程式包,將它們部署到SSIS目錄中,然後根據計劃從SQL Server代理作業中執行程式包。儘管這很好用,但我們希望能夠從應用程式執行SSIS包並在執行時指定包引數的值。
例如,我們提供了一個基於雲的CRM應用程式。我們希望推出一個完全自助服務的新客戶入職流程。當客戶註冊我們的服務時,他們需要從現有系統中獲取資料並載入到我們的應用程式中。我們將提供一個Web介面,客戶可以在其中通過簡單的CSV檔案載入其資料。Web應用程式將允許客戶導航到CSV檔案並上傳檔案。
我們怎樣才能做到這一點?
解
SQL Server整合服務(SSIS)提供了SSISDB資料庫,該資料庫包含儲存過程和檢視,使您可以使用SSIS專案和部署到Integration Services Catalog的程式包。我將採用的實現目標的方法是建立SQL物件,這些物件可以使用儲存過程從目錄中執行SSIS包。儲存過程將利用SSISDB資料庫中的物件以及一些支援物件。
這種方法有很大的好處。您已經具有可以執行的現有SSIS程式包。通過在應用程式的各個位置執行這些SSIS包,您可以重用現有過程。
作為參考,請看一下前面的技巧“
以下是實現此解決方案的概述:
- 檢視已部署到目錄的SSIS包的關鍵點
- 將SSIS專案和程式包部署到目錄後,請檢視SSIS目錄
- 詳細介紹如何建立可以執行部署到SSIS目錄的SSIS包的儲存過程
- 演示使用簡單的T-SQL執行儲存過程,並逐步執行SSIS目錄報告以檢視其工作方式的詳細資訊
SSIS程式包審查
我們的出發點是檢視將在演示中使用的SSIS軟體包。重點將放在與SSIS目錄中的部署以及從目錄中執行程式包相關的程式包部分。包裝非常簡單。它將CSV檔案從資料夾載入到SQL Server表中。
SSIS具有專案引數和程式包引數,以使SSIS程式包可重複使用。專案引數是適用於專案中多個SSIS包的引數。程式包引數是特定於單個SSIS程式包的值。SSIS目錄提供了儲存和更新引數值以及在執行程式包時指定引數值的功能。
您可以在SSIS專案下方的Visual Studio(或SQL Server資料工具)的解決方案資源管理器中看到專案引數(Project.params),如下所示:
雙擊Project.params節點以顯示專案引數:
要點如下:
- CRM_Flat_File_Folder是SSIS程式包將在其中檢查CSV檔案以載入到SQL Server表中的資料夾。通常,這將是UNC路徑(例如\\ SERVERNAME \ FOLDERNAME),但是出於演示目的,我僅使用本地計算機上的資料夾。請注意,在執行SQL Server的伺服器(本例中為本地計算機)上訪問該資料夾。
- CRM_Staging_ServerName是執行SQL Server例項的伺服器名稱。通常這不是本地計算機,但是出於演示目的,我正在使用本地計算機。
- 兩個專案引數都將Required屬性設定為True。這表明在部署到SSIS目錄時,我們應該提供不同的值。開發和測試軟體包時,將使用SSIS軟體包中的專案引數值。
您可以通過在SSIS包設計器中單擊“引數”選項卡來檢視包引數。示例程式包具有以下程式包引數:
package引數用於指定要載入的實際檔名。每次執行包時,這通常會有所不同。在建立和測試程式包時使用上面顯示的值。Required屬性為True,表示在將程式包部署到SSIS目錄時,通常是從目錄執行程式包時,需要指定一個值。例如,當您在SQL代理作業步驟中從目錄執行SSIS包時,將被迫輸入所需包引數的值。
SSIS專案目錄部署
現在,我們已經查看了樣本SSIS包,在將SSIS專案部署到Integration Service Catalog之後,我將對其進行回顧。建立Integration Services目錄,將SSIS專案部署到目錄以及建立環境涉及兩個步驟。
開啟SQL Server Management Studio(SSMS),然後導航到“物件資源管理器”中的“整合服務目錄”,如下所示:
以下是要點:
- CRM是部署專案的資料夾名稱
- CRM_OnBoarding是SSIS專案的名稱
- LoadCustomers.dtsx是SSIS專案中的SSIS程式包;我將在演示中執行它
- DEFAULT是包含專案引數值的環境的名稱
該環境具有變數及其值的列表。雙擊DEFAULT,變數和值將顯示如下:
專案引數在SSIS包中定義。通常,您使用與包中指定的值不同的值。由於這只是一個演示,所以我沒有。但是,使用環境的好處是,如果需要更改任何值,則可以在環境中更新它們,而不必更改SSIS包。SSIS專案中的任何程式包都可以在執行時使用環境變數值。
要檢視環境如何與專案連線,請右鍵單擊CRM_OnBoarding專案,然後從上下文選單中選擇“配置”。單擊“引用”後,下面將顯示“配置”視窗(您必須新增對要在SSIS專案中使用的環境的引用):
將對環境的引用新增到專案後,您可以將環境變數對映到專案引數。單擊引數,您將看到對映:
當“值”列顯示帶有下劃線的變數名稱時,該值來自具有該名稱的環境變數。您可以引用多個環境。無論您在執行時使用什麼環境,都將執行對映。
Customer_Flat_File_Name是一個包引數,因此該值顯示要使用的檔名,而不是到環境變數的對映。我將展示從儲存過程執行SSIS包時如何指定值。
建立一個儲存過程以執行SSIS包
至此,我們將逐步完成一個儲存過程,該過程將執行Integration Services Catalog中部署的SSIS包。儲存過程如下所示:
CREATE PROCEDURE [dbo].[ExecuteLoadCustomersSSISPackage] @CUSTOMER_FLAT_FILE_NAME NVARCHAR(50) , @EXECUTION_ID BIGINT OUTPUT AS BEGIN -- 1. declare variables DECLARE @PROCEDURE_NAME SYSNAME , @FOLDER_NAME NVARCHAR(128) , @PROJECT_NAME NVARCHAR(128) , @PACKAGE_NAME NVARCHAR(128) , @REFERENCE_ID BIGINT; -- 2. get this stored procedure's name SET @PROCEDURE_NAME = OBJECT_NAME(@@PROCID); -- 3. get the parameters for executing the SSIS package SELECT @FOLDER_NAME = [FOLDER_NAME] , @PROJECT_NAME = [PROJECT_NAME] , @PACKAGE_NAME = [PACKAGE_NAME] , @REFERENCE_ID = [REFERENCE_ID] FROM [dbo].[ProcedureToCreateExecutionMapping] WHERE [ProcedureName] = @PROCEDURE_NAME; -- 4. check if 1 row was returned IF @@ROWCOUNT <> 1 BEGIN -- throw error RETURN; END -- 5. create the package execution EXEC [SSISDB].[catalog].[create_execution] @folder_name = @FOLDER_NAME , @project_name = @PROJECT_NAME , @package_name = @PACKAGE_NAME , @reference_id = @REFERENCE_ID , @execution_id = @EXECUTION_ID OUTPUT; -- 6. set value for Customer_Flat_File_Name package parameter EXEC [SSISDB].[catalog].[set_execution_parameter_value] @execution_id = @EXECUTION_ID , @object_type = 30 -- package parameter , @parameter_name = N'Customer_Flat_File_Name' , @parameter_value = @CUSTOMER_FLAT_FILE_NAME; -- 7. start the execution EXEC [SSISDB].[catalog].[start_execution] @execution_id = @EXECUTION_ID; END
為了從目錄中執行SSIS包,我們需要許多值。我建立了ProcedureToCreateExecuteMapping表來儲存這些值。ProcedureName列使我可以根據正在執行的儲存過程來檢索引數值。
為了從目錄中執行SSIS包,我們必須從SSISDB資料庫中至少執行兩個儲存過程:create_execution和start_execution。在create_execution中,我們指定標識要執行的軟體包所需的詳細資訊(資料夾名稱,專案名稱和軟體包名稱)。我們還指定環境的參考ID。成功執行create_execution時,它將返回EXECUTION_ID。SSIS包尚未執行。
在create_execution之後,我們可以執行其他儲存過程。在這種情況下,我們執行set_execution_parameter_value,這使我們可以為Customer_Flat_File_Name包引數指定值。我們傳入要載入的檔名,並從create_execution返回EXECUTION_ID值。
最後,我們執行start_execution儲存過程,並傳入從create_execution返回的EXECUTION_ID值。此時,SSIS包正在執行。
在繼續執行儲存過程之前,我想澄清一個細節。ProcedureToCreateExecutionMapping表返回了[REFERENCE_ID]列(這是環境參考),將專案連線到環境。為了獲得此值,您必須執行以下查詢:
-- get the folder_id SELECT * FROM [SSISDB].[catalog].[folders] WHERE [name] = 'CRM'; -- [folder_id] = 20004 -- get the project_id SELECT * FROM [SSISDB].[catalog].[projects] WHERE [folder_id] = 20004; -- [project_id] = 40007 -- get the environment reference id SELECT * FROM [SSISDB].[catalog].[environment_references] WHERE [project_id] = 40007; -- [reference_id] = 30005
為了獲取環境參考,您必須使用SSISDB資料庫中的檢視獲取folder_id和project_id,如上所示。
執行儲存過程
現在,我們已經建立了儲存過程以從目錄中執行SSIS包,是時候執行它了。使用以下T-SQL執行儲存過程:
DECLARE @P_EXECUTION_IDBIGINT; EXEC [dbo].[ExecuteLoadCustomersSSISPackage] @CUSTOMER_FLAT_FILE_NAME=N'CustomerSample.csv' , @EXECUTION_ID= @P_EXECUTION_IDOUTPUT; SELECT @P_EXECUTION_ID; SELECT [start_time] , [end_time] , [status] FROM [SSISDB].[catalog].[executions] WHERE [execution_id]= @P_EXECUTION_ID;
SSISDB.catalog.create_execution儲存過程返回了@execution_id OUTPUT引數。上面的儲存過程也將它作為OUTPUT引數返回。要檢查SSIS包的狀態,請檢查[SSISDB]。[catalog]。[executions]檢視。[status]列具有成功= 7的多個可能值。檢查catalog.executions以獲取詳細資訊。在SSIS包失敗或成功之前,您可能必須多次查詢catalog.executions。
SSIS目錄提供有關SSIS包執行的詳細資訊。返回到SSMS Object Explorer中的Integration Services目錄,右鍵單擊SSIS包,選擇“報告”,“標準報告”和“所有執行”,如下所示:
執行細節將顯示如下:
在上述情況下,您可以看到執行成功。有多個連結可用於檢索其他詳細資訊。我將在“概述”連結上介紹關鍵點:執行概述和使用的引數。
“執行概述”顯示SSIS包中已執行的任務以及“執行路徑”列中的連結,以提供更多資訊:
使用的引數顯示專案和包引數的實際值,以及其他一些資訊:
在進行故障排除時,能夠檢視所使用的實際值非常有用。