寻求SSIS之外支持单表单包的SFTP多表压缩传输替代方案
我来给你几个实用的替代方案,完全满足你的需求,而且不用依赖SSIS的SFTP插件:
方案1:PowerShell脚本(Windows环境首选)
这个方案上手快,Windows系统自带PowerShell,搭配几个轻量工具就能搞定:
步骤1:读取待传输的表列表
用Invoke-SqlCmd从你的表驱动表中获取所有需要传输的表名,比如:$serverName = "YourSQLServer" $dbName = "YourDatabase" $tableListQuery = "SELECT TableName FROM dbo.YourTableList" $tables = Invoke-SqlCmd -ServerInstance $serverName -Database $dbName -Query $tableListQuery步骤2:逐个导出并压缩表
循环每个表,用bcp命令导出CSV(速度比PowerShell直接导出快),再用Compress-Archive生成单独的压缩包:$exportPath = "C:\Temp\Exports" New-Item -Path $exportPath -ItemType Directory -Force | Out-Null foreach ($table in $tables) { $tableName = $table.TableName $csvPath = Join-Path $exportPath "$tableName.csv" $zipPath = Join-Path $exportPath "$tableName.zip" # 用bcp导出数据 bcp "$dbName.dbo.$tableName" out $csvPath -S $serverName -c -t, -T # 压缩成单独的zip包 Compress-Archive -Path $csvPath -DestinationPath $zipPath -Force Remove-Item $csvPath # 导出的CSV可以删除,只保留压缩包 }步骤3:SFTP上传压缩包
用WinSCP的命令行工具winscp.com实现SFTP传输(需要先下载WinSCP并配置环境变量),示例脚本:$sftpHost = "TargetSFTPHost" $sftpUser = "SFTPUser" $sftpPass = "SFTPPassword" $sftpRemotePath = "/remote/directory" foreach ($table in $tables) { $tableName = $table.TableName $zipPath = Join-Path $exportPath "$tableName.zip" # WinSCP命令行上传 & winscp.com /command "open sftp://$sftpUser:$sftpPass@$sftpHost" ` "put `"$zipPath`" `"$sftpRemotePath/`"" ` "exit" }
方案2:Python脚本(跨平台通用)
如果需要跨Windows/Linux环境,Python是更好的选择,灵活性极高:
步骤1:准备依赖
先安装需要的库:pip install pyodbc pandas paramiko(zipfile是Python标准库,无需额外安装)步骤2:读取表列表并处理
import pyodbc import pandas as pd import zipfile import paramiko import os # 数据库连接配置 conn_str = ( "DRIVER={ODBC Driver 17 for SQL Server};" "SERVER=YourSQLServer;" "DATABASE=YourDatabase;" "Trusted_Connection=yes;" ) export_path = "/tmp/exports" os.makedirs(export_path, exist_ok=True) # 读取待传输表列表 with pyodbc.connect(conn_str) as conn: cursor = conn.cursor() cursor.execute("SELECT TableName FROM dbo.YourTableList") tables = [row[0] for row in cursor.fetchall()] # 逐个导出、压缩 for table_name in tables: csv_path = os.path.join(export_path, f"{table_name}.csv") zip_path = os.path.join(export_path, f"{table_name}.zip") # 用pandas导出表数据 df = pd.read_sql(f"SELECT * FROM dbo.{table_name}", conn) df.to_csv(csv_path, index=False) # 压缩成单独的zip包 with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf: zipf.write(csv_path, os.path.basename(csv_path)) os.remove(csv_path) # SFTP上传 ssh_client = paramiko.SSHClient() ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh_client.connect(hostname="TargetSFTPHost", username="SFTPUser", password="SFTPPassword") sftp = ssh_client.open_sftp() remote_path = "/remote/directory" for table_name in tables: zip_path = os.path.join(export_path, f"{table_name}.zip") sftp.put(zip_path, os.path.join(remote_path, f"{table_name}.zip")) sftp.close() ssh_client.close()
方案3:SQL Server Agent + 命令行工具(纯SQL运维场景)
如果你的团队更熟悉SQL Server生态,不用额外脚本语言,直接用SQL Server Agent配合命令行工具也能实现:
步骤1:创建存储过程生成执行命令
写一个存储过程,循环读取表列表,生成每个表的bcp导出、7z压缩、winscp上传命令,比如:CREATE PROCEDURE dbo.GenerateTransferCommands AS BEGIN DECLARE @TableName NVARCHAR(128), @Cmd NVARCHAR(MAX) DECLARE @ExportPath NVARCHAR(256) = 'C:\Temp\Exports', @SftpHost NVARCHAR(128) = 'TargetSFTPHost', @SftpUser NVARCHAR(128) = 'SFTPUser', @SftpPass NVARCHAR(128) = 'SFTPPassword' DECLARE TableCursor CURSOR FOR SELECT TableName FROM dbo.YourTableList OPEN TableCursor FETCH NEXT FROM TableCursor INTO @TableName WHILE @@FETCH_STATUS = 0 BEGIN -- 生成bcp导出命令 SET @Cmd = 'bcp "YourDatabase.dbo.' + @TableName + '" out "' + @ExportPath + '\' + @TableName + '.csv" -S YourSQLServer -c -t, -T' EXEC xp_cmdshell @Cmd -- 生成7z压缩命令(需要7-Zip命令行工具) SET @Cmd = '7z a "' + @ExportPath + '\' + @TableName + '.zip" "' + @ExportPath + '\' + @TableName + '.csv"' EXEC xp_cmdshell @Cmd -- 生成WinSCP上传命令 SET @Cmd = 'winscp.com /command "open sftp://' + @SftpUser + ':' + @SftpPass + '@' + @SftpHost + '" "put "' + @ExportPath + '\' + @TableName + '.zip" "/remote/directory/" "exit"' EXEC xp_cmdshell @Cmd -- 删除临时CSV文件 SET @Cmd = 'del "' + @ExportPath + '\' + @TableName + '.csv"' EXEC xp_cmdshell @Cmd FETCH NEXT FROM TableCursor INTO @TableName END CLOSE TableCursor DEALLOCATE TableCursor END步骤2:配置SQL Server Agent作业
创建一个新作业,添加一个“Transact-SQL (T-SQL)”步骤,调用上面的存储过程EXEC dbo.GenerateTransferCommands,然后设置定时执行即可。
方案对比
- PowerShell:适合Windows管理员,工具易获取,语法贴近批处理,学习成本低
- Python:跨平台,扩展性强,适合复杂数据处理场景
- SQL Server Agent:纯SQL环境,不需要额外学习脚本语言,适合运维团队
内容的提问来源于stack exchange,提问作者navig8tr

