如何基于文件列表自动选择执行指定SSIS包?
基于FileList自动执行对应SSIS包的解决方案
当然可以实现你的需求!而且有几种不同的思路,根据你的场景,我推荐以下几种最实用的方案:
方案一:SSIS主包+Foreach循环动态执行(最推荐)
这种方式不需要禁用任何包,直接只触发存在对应文件的包,逻辑清晰易维护:
- 添加Execute SQL Task:在主包中新增一个执行SQL任务,查询
[dbo].[FileList]获取文件名,同时处理文件名和包名的映射(比如把Sales_2018.csv转换成Sales),SQL语句示例:
将查询结果存储到一个对象类型变量(比如SELECT REPLACE(REPLACE([FileName], '.csv', ''), '_2018', '') AS PackageName FROM [dbo].[FileList]User::ValidPackageNames)中。 - 添加Foreach Loop Container:配置循环容器遍历
User::ValidPackageNames,每次循环将当前包名存储到一个字符串变量(比如User::CurrentPackage)。 - 添加动态执行包任务:在循环容器内放置
Execute Package Task,设置它的PackageName属性为表达式:@[User::CurrentPackage] + ".dtsx"。这样循环过程中只会执行匹配到的包,无关的包根本不会被触发。
方案二:SQL Server Agent作业动态生成执行命令
如果你的SSIS包是通过Agent调度的,可以用T-SQL动态生成执行命令,只运行需要的包:
- 编写一个T-SQL脚本,查询
[dbo].[FileList]并生成SSIS目录的执行语句(假设用项目部署模型):DECLARE @execution_id BIGINT; DECLARE @cmd NVARCHAR(MAX) = N''; -- 生成每个匹配包的执行命令 SELECT @cmd += N' EXEC [SSISDB].[catalog].[create_execution] @folder_name = N''YourSSISFolder'', @project_name = N''YourSSISProject'', @package_name = N''' + REPLACE(REPLACE([FileName], '.csv', ''), '_2018', '') + N'.dtsx'', @use32bitruntime = 0, @execution_id = @execution_id OUTPUT; EXEC [SSISDB].[catalog].[start_execution] @execution_id; ' FROM [dbo].[FileList]; -- 执行动态生成的命令 EXEC sp_executesql @cmd; - 将这个脚本作为Agent作业的一个步骤,每次运行时自动执行所有匹配的包。
方案三:动态禁用无关包(不推荐,仅作参考)
如果一定要通过“禁用”无关包的方式实现,可以用脚本任务修改SSIS包的属性,但这种方式复杂度较高,适合特殊场景:
在主包中添加一个Script Task,用C#代码查询[dbo].[FileList],然后遍历控制流中的所有执行包任务,将不在匹配列表中的任务设为禁用:
using System; using System.Collections.Generic; using System.Data.SqlClient; using Microsoft.SqlServer.Dts.Runtime; public void Main() { // 获取当前主包对象 Package mainPackage = (Package)Dts.Variables["System::Package"].Value; string dbConnStr = Dts.Variables["User::DBConnectionString"].Value.ToString(); List<string> validPackages = new List<string>(); // 从数据库读取有效包名 using (SqlConnection conn = new SqlConnection(dbConnStr)) { conn.Open(); string query = "SELECT REPLACE(REPLACE(FileName, '.csv', ''), '_2018', '') FROM dbo.FileList"; using (SqlCommand cmd = new SqlCommand(query, conn)) { using (SqlDataReader reader = cmd.ExecuteReader()) { while (reader.Read()) { validPackages.Add(reader.GetString(0)); } } } } // 遍历所有执行包任务,禁用不匹配的 foreach (Executable exec in mainPackage.Executables) { if (exec is ExecutePackageTask epTask) { string pkgName = System.IO.Path.GetFileNameWithoutExtension(epTask.PackageName); if (!validPackages.Contains(pkgName)) { epTask.Disabled = true; } } } Dts.TaskResult = (int)ScriptResults.Success; }
注意:这种方式需要确保包是文件部署模型,或者在项目部署中调整权限,且不如前两种方案灵活。
内容的提问来源于stack exchange,提问作者RandyMcKay
相关产品推荐
相关产品推荐

