连续运行 SQL 代理作业 3 次

2 data-warehouse sql-server jobs sql-server-2016

如何连续执行 3 次 SQL Agent 作业?

我们正在创建数据仓库项目。它从 Flatfile Legacy 文件夹 ETL 数据,并创建 Dim 和 Fact 表。

SSIS 项目环境变量 (FlatfileFolder) 设置:至 2018 年 3 月

  1. 将 ETL 平面文件导入 2018 年 3 月的临时数据库
  2. 创建客户维度表
  3. 创建产品维度表
  4. 创建 SalesTransaction 事实表

想连续执行3次,将项目环境变量(FlatfileFolder)改为2018年4月。再次运行4个作业,然后将项目环境变量(FlatfileFolder)改为2018年5月,再次运行4个作业步骤。(理论上,应该被设计为提取所有历史文件并立即加载,但没有设计这个,只是继承它。)

下面这个堆栈​​链接谈到了无限循环,只想运行 3 次,并更改环境变量。

在无限循环中运行作业

选项:

(a) 写 12 Step SQL Agent Job,

(b) 或者在第 4 步之后以某种方式成功返回第 1 步?如何让它只运行3次?

最终可能希望在以后的几个月中连续执行 5-10 次作业。尝试使用 SQL 环境进行操作,除非需要,否则最好不要使用 C# 或 Powershell。

我们正在处理数据。

谢谢,

Sco*_*red 6

我想我会这样解决:

  • 创建一个驱动存储过程,以确定是否需要完成工作。这可能意味着检查要处理的下一个文件夹月份的表格。此驱动表将预先填充需要处理的文件夹数(月)。您可能希望包含一种方法来确定要处理的文件夹的顺序,以便以正确的顺序处理它们。
  • 设置一个WHILE LOOP检查IF工作是必须要做的。使用自定义存储过程sp_sp_start_job_wait调用具有 4 个步骤的作业。此过程将启动作业并等待它完成。
  • 成功完成作业后,标记为完成删除您刚刚处理的月份的文件夹行。
  • WHILE LOOP重新迭代以检查更多的工作要做。

要启动整个过程,只需调用驱动存储过程。


您还可以完全消除对 SQL 代理作业的需求,只需使用内置存储过程直接从我之前描述的驱动存储过程调用 SSIS 包;例如ssisdb.catalog.create_executionssisdb.catalog.start_execution。有一篇很好的博客文章描述了如何从 SQL Server 存储过程执行集成服务 (SSIS) 包的过程。总结该帖子的要点:

create procedure dbo.execute_ssis_package_sample
 @output_execution_id bigint output
as
begin
 declare @execution_id bigint
 exec ssisdb.catalog.create_execution 
  @folder_name = 'mssqltips'
 ,@project_name = 'exec-ssis-stored-proc-ssis-sample'
 ,@package_name = 'Sample.dtsx'
 ,@execution_id = @execution_id output
 exec ssisdb.catalog.start_execution @execution_id
 set @output_execution_id = @execution_id
end
Run Code Online (Sandbox Code Playgroud)
  • 调用存储过程 ssisdb.catalog.create_execution(SSIS 2012 中的新增功能)来创建 SSIS 包执行的实例。
  • 您将文件夹、项目和包传递给 ssisdb.catalog.create_execution 存储过程。
  • ssisdb.catalog.create_execution 返回一个名为@execution_id 的输出参数;您需要此值来开始执行 SSIS 包以及检查包执行的状态。
  • 调用 ssisdb.catalog.start_execution 存储过程(SSIS 2012 中的新增功能)来开始包的实际执行。
  • SSIS 包执行是异步的;即当您调用 ssisdb.catalog.start_execution 存储过程时,您不是在等待包完成。

我强调指出的默认行为ssisdb.catalog.start_execution是运行异步的,但作为记录在为一种变通方法这篇文章蒂姆·米切尔。请参阅同步执行包部分。引用那篇文章:

这是一个相对容易的修复。尽管默认行为是异步执行 [catalog].[start_execution],但有一个系统参数可让您在每次执行的基础上覆盖此行为。参数名称是 SYNCHRONIZED,它期望值为 0(不同步,默认行为)或 1(同步)。当覆盖此值并将其设置为 1 时,对 [catalog].[start_execution] 的调用将不会返回,直到包完成其执行。这意味着只要包仍在运行,[catalog].[start_execution] 就会运行。添加此参数的语法如下所示。

-- Create the execution object
DECLARE @execution_id BIGINT
EXEC [SSISDB].[catalog].[create_execution] 
    @package_name = N'Package1.dtsx'
    , @project_name = N'Project1'
    , @folder_name = N'Folder1'
    , @use32bitruntime = False
    , @reference_id = NULL
    , @execution_id = @execution_id OUTPUT

-- System parameters
EXEC [SSISDB].[catalog].[set_execution_parameter_value] 
    @execution_id
    , @object_type = 50                     -- System parameter
    , @parameter_name = N'SYNCHRONIZED'
    , @parameter_value = 1

-- Execute the package
EXEC [SSISDB].[catalog].[start_execution] @execution_id
Run Code Online (Sandbox Code Playgroud)

如图,在[catalog].[create_execution]之后和[catalog].[start_execution]之前添加参数值(包括系统、项目和包参数)。在上面的示例中,我将 SYNCHRONIZED 系统参数设置为 1,强制 [catalog].[start_execution] 等待包完成后再返回。

此覆盖解决了一个问题,但留下了另一个问题:即使 [catalog].[start_execution] 现在同步运行,它也不会报告包执行的状态。大多数工作流需要知道包执行的状态,而不仅仅是执行已完成。幸运的是,也有一种解决方法。

如果包失败,则强制执行脚本失败

这种变通方法需要的不仅仅是一个简单的执行参数,因此它有更多的活动部件。简而言之,这里是强制 T-SQL 脚本在它调用的包失败的情况下失败的设计模式:

  • 创建执行
  • 将 SYNCHRONIZED 参数设置为 1
  • 执行包
  • 检查本次执行的执行日志,如果打包失败则强制T-SQL脚本失败

前面的脚本已经处理了步骤 1-3,所以我们只需要添加最后一步。这可以根据需要简单或复杂,但在我的示例中,我只检查 [catalog].[executions] 并检索该执行的 [status] 值;如果该值不等于 7(成功的状态 ID),脚本将使用 RAISERROR 生成失败。

-- Create the execution object
DECLARE @execution_id BIGINT
EXEC [SSISDB].[catalog].[create_execution] 
    @package_name = N'Package2.dtsx'
    , @project_name = N'Project1'
    , @folder_name = N'Folder1'
    , @use32bitruntime = False
    , @reference_id = NULL
    , @execution_id = @execution_id OUTPUT

-- System parameters
EXEC [SSISDB].[catalog].[set_execution_parameter_value] 
    @execution_id
    , @object_type = 50                     -- System parameter
    , @parameter_name = N'SYNCHRONIZED'
    , @parameter_value = 1

-- Execute the package
EXEC [SSISDB].[catalog].[start_execution] @execution_id

-- Check package status, and fail script if the package failed
IF 7 <> (SELECT [status] FROM [SSISDB].[catalog].[executions] WHERE execution_id = @execution_id)
RAISERROR('The package failed. Check the SSIS catalog logs for more information', 16, 1)
Run Code Online (Sandbox Code Playgroud)