SSIS ForEach循环按客户账号生成独立发票文件的实现方法
按客户分发生成独立发票文件:SSIS ForEach循环实现+替代方案
嘿,刚好我之前做过几乎一模一样的需求,结合你的SQL Server 2014和SSIS 2012环境,给你两种靠谱的实现方式,包括你问的ForEach循环方案,还有更适合小数据量的捷径:
方案一:用ForEach循环容器+ADO枚举器实现按客户循环
这完全匹配你想用ForEach循环的需求,核心是先拿到唯一的客户列表,再循环每个客户导出数据:
获取唯一客户列表
- 在SSIS控制流里拖一个「执行SQL任务」,编写查询:
SELECT DISTINCT AccountNumber FROM 你的发票表名 - 任务配置里,把结果集设为「完整结果集」,然后在「结果集」选项卡中,把结果映射到一个对象类型的变量(比如
@User::AccountList,记得提前在变量面板创建这个变量)。
- 在SSIS控制流里拖一个「执行SQL任务」,编写查询:
配置ForEach循环容器
- 拖一个「ForEach循环容器」到控制流,双击编辑:
- 「枚举器」选择Foreach ADO枚举器,数据源选刚才的
@User::AccountList - 「枚举模式」选「第一行的每一列」
- 切换到「变量映射」,把枚举出来的AccountNumber值绑定到一个字符串类型的变量(比如
@User::CurrentAccount,索引设为0)。
- 「枚举器」选择Foreach ADO枚举器,数据源选刚才的
- 拖一个「ForEach循环容器」到控制流,双击编辑:
循环内实现数据导出
- 把「数据流任务」拖进ForEach循环容器里:
- 数据流里用「OLE DB源」连接数据库,编写带参数的查询:
SELECT AccountNumber, InvoiceNumber, OriginalCharge FROM 你的发票表名 WHERE AccountNumber = ? - 在「OLE DB源」的「参数映射」里,把
@User::CurrentAccount绑定到这个参数(参数名称一般是0或者@P1,根据你的驱动调整) - 拖一个「平面文件目标」,配置文件路径时用表达式动态生成文件名:比如
"C:\\Invoice_Export\\Invoice_" + @[User::CurrentAccount] + ".csv"(记得提前创建好导出目录) - 配置平面文件的列映射,确保和源表字段对应。
- 数据流里用「OLE DB源」连接数据库,编写带参数的查询:
- 把「数据流任务」拖进ForEach循环容器里:
方案二:T-SQL批量导出(更高效,适合小数据量)
因为你的总数据量不到5000条,完全可以跳过SSIS的循环逻辑,用T-SQL直接生成所有文件,速度更快,步骤更简单:
- 先创建一个存储过程(替换掉你的数据库、表名、服务器名和导出路径):
CREATE PROCEDURE dbo.ExportInvoicesPerAccount AS BEGIN SET NOCOUNT ON; DECLARE @Account VARCHAR(10), @bcpCommand VARCHAR(1000); -- 遍历所有唯一客户 DECLARE AccountCursor CURSOR FOR SELECT DISTINCT AccountNumber FROM 你的发票表名; OPEN AccountCursor; FETCH NEXT FROM AccountCursor INTO @Account; WHILE @@FETCH_STATUS = 0 BEGIN -- 拼接bcp导出命令 SET @bcpCommand = 'bcp "SELECT AccountNumber, InvoiceNumber, OriginalCharge FROM 你的数据库名.dbo.你的发票表名 WHERE AccountNumber = ''' + @Account + '''" queryout "C:\\Invoice_Export\\Invoice_' + @Account + '.csv" -S 你的SQL服务器名 -T -c -t,'; -- 执行导出命令 EXEC master.dbo.xp_cmdshell @bcpCommand; FETCH NEXT FROM AccountCursor INTO @Account; END CLOSE AccountCursor; DEALLOCATE AccountCursor; END
- 执行存储过程前,确保:
- SQL Server服务账号有导出目录的读写权限
- 开启了
xp_cmdshell(如果没开,执行以下语句开启):
sp_configure 'show advanced options', 1; RECONFIGURE; sp_configure 'xp_cmdshell', 1; RECONFIGURE;
- 最后在SSIS里用「执行SQL任务」调用这个存储过程,或者直接在SSMS里执行即可。
方案对比
- 如果你需要复杂的数据转换、格式控制(比如导出Excel、自定义文件格式),选SSIS的ForEach循环方案更灵活;
- 如果你只是导出简单的CSV/文本文件,T-SQL方案更高效,不需要搭建复杂的SSIS包流程。
内容的提问来源于stack exchange,提问作者Jeremy
相关产品推荐
相关产品推荐

