美文网首页ssis
T-SQL存储过程调用SSIS Package

T-SQL存储过程调用SSIS Package

作者: quietseason | 来源:发表于2017-02-20 17:46 被阅读0次
    为什么需要用存储过程调用SSIS Package?

    可以综合利用存储过程和SSIS Package各自的优点。如Package中有很多现成的component直接使用,而存储过程中实现同样功能则需要大费周章;存储过程的传参灵活方便,而Package的传入参数如果是经常需要变化的,就比较麻烦了。

    两种方法

    1、调用SSISDB内置的存储过程

    如果SSIS Package是部署在SQL Server的Integration Services Catalogs上的话,可以利用SSISDB中的几个内置存储过程来实现功能。

    注意:调用以此方法写就的存储过程时需要用Windows Authentication方式登录数据库

    示例存储过程用到一个自定义表变量PACKAGEVARIABLES,需要事先定义:

    IF NOT EXISTS(SELECT * FROM  sys.table_types)
    CREATE TYPE [dbo].[PackageVariables] AS TABLE ( 
      [id] INT IDENTITY (1, 1) NOT NULL,
      [property_path] NVARCHAR (4000) NOT NULL, 
      [property_value] NVARCHAR (MAX) NOT NULL, 
      [sensitive] BIT DEFAULT ((0)) NOT NULL
    );
    

    存储过程实现代码如下:

    CREATE PROC [dbo].[usp_CallSSISPackage] @package_name    NVARCHAR(260),--包名称
                                            @folder_name     NVARCHAR(128),--IS Catagory文件夹名
                                            @project_name    NVARCHAR(128),--IS Catagory项目名称
                                            @use32bitruntime BIT=FALSE,--以32位运行还是64位
                                            @delay           VARCHAR(100)='00:00:30',--package启动后每隔多久查看一次运行情况
                                            @maxExecMinutes  INT=60,--超时分钟数,超过这个时间则不再继续等待
                                            @variables       PACKAGEVARIABLES READONLY,--自定义数据类型
                                            @status          INT OUTPUT,--0:Succeeded 1:Failed package运行状态
                                            @execution_id    BIGINT OUTPUT--SSISDB自动生成的execution_id
    AS
      BEGIN
          /*
          --Example:
          
          DECLARE @variables AS PACKAGEVARIABLES;
          DECLARE @pkgStatus INT;
          DECLARE @execution_id BIGINT;
          INSERT INTO @variables
                    (property_path,
                     property_value)
          VALUES      (N'\Package.Variables[User::var1].Value',
                     @script);
          
          INSERT INTO @variables
                    (property_path,
                     property_value)
          VALUES      (N'\Package.Variables[User::var2].Value',
                     @database);
          
          INSERT INTO @variables
                    (property_path,
                     property_value)
          VALUES      (N'\Package.Variables[User::var3].Value',
                     @level);
          
          INSERT INTO @variables
                    (property_path,
                     property_value)
          VALUES      (N'\Package.Variables[User::var4].Value',
                     @operation_type);
          
          EXEC [dbo].[usp_CallSSISPackage]
          @package_name=N'MyPackage.dtsx',
          @folder_name=N'MySolution',
          @project_name=N'MyProject',
          @variables=@variables,
          @status=@pkgStatus,
          @execution_id=@execution_id;
          */
          SET NOCOUNT ON;
    
          DECLARE @property_path NVARCHAR(4000);
          DECLARE @property_value NVARCHAR(MAX);
          DECLARE @sensitive BIT;
          DECLARE @i INT=1;
          DECLARE @max INT;
          DECLARE @runningStatus INT;
          DECLARE @isBufferUsed BIT = 0;
          DECLARE @statusReport VARCHAR(500);
          DECLARE @pkgStartTime DATETIME = GETDATE();
          DECLARE @errMsg NVARCHAR(2048);
          DECLARE @errSev INT;
          DECLARE @errState INT;
    
          BEGIN TRY
              SELECT @max = ISNULL(MAX(id), 0)
              FROM   @variables;
    
              EXEC [SSISDB].[catalog].[create_execution]
                @package_name=@package_name,
                @execution_id=@execution_id OUTPUT,
                @folder_name=@folder_name,
                @project_name=@project_name,
                @use32bitruntime=False,
                @reference_id=NULL
    
              DECLARE @var0 SMALLINT = 1
    
              EXEC [SSISDB].[catalog].[set_execution_parameter_value]
                @execution_id,
                @object_type=50,
                @parameter_name=N'LOGGING_LEVEL',
                @parameter_value=@var0
    
              WHILE @i <= @max
                BEGIN
                    SELECT @property_path = property_path,
                           @property_value = property_value,
                           @sensitive = sensitive
                    FROM   @variables
                    WHERE  id = @i;
    
                    EXEC [SSISDB].[catalog].[set_execution_property_override_value]
                      @execution_id,
                      @property_path,
                      @property_value,
                      @sensitive
    
                    SET @i=@i + 1;
                END
    
              EXEC [SSISDB].[catalog].[start_execution]
                @execution_id
    
              SET @statusReport='Started to execute ' + @package_name;
    
              RAISERROR(@statusReport,0,1) WITH NOWAIT;
    
              --Monitor the log
              WHILE @runningStatus IN( 1, 2, 5, 8 )
                     OR @runningStatus IS NULL
                BEGIN
                    WHILE @runningStatus IS NOT NULL
                           OR @isBufferUsed = 0
                      BEGIN
                          SELECT @runningStatus = [Status]
                          FROM   SSISDB.[catalog].[executions] WITH(NOLOCK)
                          WHERE  execution_id = @execution_id;
    
                          SET @statusReport = 'Running Status is '
                                              + CAST(@runningStatus AS VARCHAR(20));
    
                          RAISERROR(@statusReport,0,1) WITH NOWAIT;
    
                          IF @runningStatus IS NULL
                            BEGIN
                                RAISERROR('Execution log is not found yet. Wait for 30 seconds...',0,1) WITH NOWAIT;
    
                                WAITFOR DELAY '00:00:30';
    
                                SET @isBufferUsed = 1;
                            END
                          ELSE
                            BREAK;
                      END
    
                    IF @runningStatus IS NULL
                      BEGIN
                          RAISERROR('Execution log is not found after waiting for 30 seconds. Please check the status and update ProcessFlag mannually!',0,1) WITH NOWAIT;
    
                          SET @status = 1;
    
                          BREAK;
                      END
                    ELSE IF @runningStatus IN( 1, 2, 5, 8 )
                      BEGIN
                          SET @statusReport = 'The package is ' + CASE @runningStatus WHEN 1 THEN 'created' WHEN 2 THEN 'running' WHEN 5 THEN 'pending' WHEN 8 THEN 'stopping' END + '. Wait for ' + @delay
                                              + '...';
    
                          RAISERROR(@statusReport,0,1) WITH NOWAIT;
    
                          WAITFOR DELAY @delay;
                      END
                    ELSE
                      BEGIN
                          SET @statusReport = 'The package is ' + CASE @runningStatus WHEN 3 THEN 'canceled' WHEN 4 THEN 'failed' WHEN 6 THEN 'ended unexceptedly' WHEN 7 THEN 'succeeded' WHEN 9 THEN 'completed' END
    
                          RAISERROR(@statusReport,0,1) WITH NOWAIT;
    
                          SET @status = CASE @runningStatus
                                          WHEN 7 THEN 0
                                          ELSE 1
                                        END;
                      END
    
                    IF DATEDIFF(MINUTE, @pkgStartTime, GETDATE()) >= @maxExecMinutes
                      BEGIN
                          RAISERROR('The package execution timed out! Please check the status and update ProcessFlag mannually!',0,1) WITH NOWAIT;
    
                          SET @status = 1;
    
                          BREAK;
                      END
                END
          END TRY
    
          BEGIN CATCH
              SET @errMsg=ERROR_MESSAGE();
              SET @errSev=ERROR_SEVERITY();
              SET @errState=ERROR_STATE();
    
              RAISERROR(@errMsg,@errSev,@errState) WITH NOWAIT;
    
              SET @status = 1;
    
              RETURN;
          END CATCH
      END
    

    2、调用dtexec命令
    如果SSIS Package是以File System形式存放,则需要调用dtexec命令了。
    虽然这种方法对于package部署在IS Catagory上的情况也适用,但由于无法直接通过return code来判断package运行成功与否,不推荐。
    存储过程的核心代码如下:

    --Config for dtexec
    EXEC sp_configure
      'show advanced options',
      1;
    
    RECONFIGURE;
    EXEC sp_configure
      'xp_cmdshell',
      1;
    
    DECLARE @cmd        VARCHAR(8000),
            @returncode INT
    DECLARE @val1 VARCHAR(255),
            @val2 VARCHAR(255),
            @val3 VARCHAR(255)
    
    SET @val1 = 'Value 1'
    SET @val2 = 'Value 2'
    SET @val3 = 'Value 3'
    SET @cmd1='dtexec /Rep e /FILE "\"E:\MySolution\MyProject\MyPackage.dtsx\"" /SET \Package.Variables[User::var1].Value;"'
              + @val1
              + '"  /SET \Package.Variables[User::var2].Value;"'
              + @val2
              + '" /SET \Package.Variables[User::var3].Value;"'
              + @val3 + '"'
    
    EXEC @returncode = xp_cmdshell--0:Succeeded 1:Failed
      @cmd
    

    相关文章

      网友评论

        本文标题:T-SQL存储过程调用SSIS Package

        本文链接:https://www.haomeiwen.com/subject/irqjwttx.html