在这个答案中,我将尝试提供一些信息并提供一个工作示例,将具有不同元数据的多个平面文件导入到单独的 SQL Server 表中。
SSIS 限制
由于 SSIS requires fixed metadata of the data source and destination,我建议使用 C# 代码而不是自动创建 SSIS 包。如果需要 SSIS,您应该使用脚本任务来完成该任务。
在类似的情况下,我一般使用 C# 或其他脚本语言,例如 python。
为什么不应该自动生成 SSIS 包?
将 100 多个平面文件导入应在运行时创建的 100 多个表(没有固定结构)需要创建 100 多个 SSIS 包。即使使用SSIS automation tools 之一自动执行此过程,也很难管理和调试大量 SSIS 包。
统一的 SQL Server 目标表?
如果目标表结构大多具有相似的结构,最好使用架构映射的方式将所有平面文件导入到统一的SQL Server目标中,可以参考以下答案:
解决方案概述
此解决方案中提供的所有代码都可以改进,但它是作为原型编写的
读取平面文件
我创建了一个类TextImport,它尝试遍历给定目录中的所有平面文件,读取平面文件元数据并将每个文件数据存储在System.Data.DataTable 对象中。 (请注意,应添加 Microsoft.VisualBasic 程序集作为引用以使用 TextFieldParser 类)
TextImport txtimp = new TextImport(filename, true, 0); // TextImport(string filename, bool containsHeader, int RowsToSkip)
txtimp.BuildDataTableStructure(); //Read flat file metadata
DataTable dt = txtimp.FillDataTable(); //Convert the flat file to a DataTable object
TextImport 类尝试根据前 8 行检测文件元数据(列数、分隔符、文本限定符、编码)(任意数字)在平面文件中。
创建 SQL 目标表
然后这个System.Data.DataTable 被传递给另一个名为SQLExport 的类,该类根据DataTable 元数据生成并执行CREATE TABLE 语句。
SQLExport.CreateDestinationTable(DataTable dt);
向 SQL 中插入数据
最后提供了两种插入方法:
- 生成
INSERT INTO () ... VALUES (),(),()... 语句并执行它以将数据插入到 SQL 目标中
- 使用
System.Data.SqlClient.SqlBulkCopy类通过BULK INSERT方法插入数据。
主要代码应如下所示:
static void Main(string[] args)
{
//You should set your database connection string
string connectionstring = @"Data Source=.\SQLINSTANCE;Initial Catalog=tempdb;integrated security=SSPI;";
//This is the schema of the destination table
string Schema = "upload";
//You should set the text files directory
string directory = @"E:\TextFiles";
using (SQLExport sqlExp = new SQLExport(connectionstring, Schema))
{
//if you don't want to traverse subfolders use System.IO.SearchOption.TopDirectoryOnly
foreach (string filename in System.IO.Directory.GetFiles(directory,
"*.txt",System.IO.SearchOption.AllDirectories)){
using(TextImport txtimp = new TextImport(filename, true, 0))
{
txtimp.BuildDataTableStructure();
DataTable dt = txtimp.FillDataTable();
dt.TableName = System.IO.Path.GetFileName(filename);
sqlExp.CreateDestinationTable(dt);
//Insert using BULK INSERT
sqlExp.InsertUsingSQLBulk(dt);
//Creates and Execute an INSERT INTO statment
//sqlExp.InsertIntoDb(dt);
}
}
}
}
测试
我在the following link上存储的两个平面文件上测试了这个解决方案(我的谷歌搜索的第一个结果),如下图所示,表创建成功,数据插入。
请注意,所有列都创建为 NVARCHAR(255),您可以在 SQLExport.cs 文件中更改此设置
您可以在以下 GitHub 存储库中查看完整代码(.NET Framework 4.6.1 C# 控制台应用程序):
如果您决定使用 Script Task 来运行此代码,您应该只将 GitHub 项目中的类复制到您的 Script Task 项目中记得添加 Microsoft.VisualBasic 作为参考。 p>
如何从 SQL Server 代理作业运行 C# 控制台应用程序?
您可以简单地编辑 C# 控制台应用程序以将连接字符串和文本文件目录作为参数传递,然后使用 cmdExec 作业步骤运行它:
甚至使用 SSIS 包:
替代方案 - 使用任务计划程序
另一种方法是使用 Windows 任务计划程序定期运行 C# 控制台应用程序。