【问题标题】:ssis - load multiple csv with different structure to sql serverssis - 将具有不同结构的多个csv加载到sql server
【发布时间】:2019-06-10 06:14:15
【问题描述】:

我有多个结构不同(列数不同,列名不同)的 CSV 文件(超过 60 个),我想将它们加载到 SQL Server 表中。

  • 每个 CSV 文件都将加载到不同的表中。
  • SSIS 进程需要自动创建具有 CSV 结构的表,并将 CSV 数据加载到表中。

我该怎么做?

【问题讨论】:

  • SSIS 处理静态元数据,因此您将无法动态执行此操作。最好的办法是使用 c#、java 或类似的自定义应用程序来推断 CSV 的内容,创建具有正确数据类型的表并加载它。
  • 为什么选择 SSIS?您的(模糊)描述听起来像是您的服务器上已经存在这些表,因此使用 BCP 或 BULK INSERT 可能会更好;当然,每个文件都需要有自己的命令,但是如果已经创建了定义,那么除了源文件和目标表名之外不会有太大区别。
  • 你可能想看看 BIML
  • EzAPI 也是 BIML 的替代品

标签: sql-server ssis ssis-2012 ssis-2008


【解决方案1】:

您“可以”尝试以下方法。

创建一个包含 1 列的暂存表来存储数据。 VARCHAR(MAX) + 1 col 存储文件名

然后设置您的 SSIS 以将每一行加载到此列中(无列分隔符) 您可能还需要将 Header 作为数据行加载以获取 col 名称。

然后你可以 ForEach 循环进入这个表

最后,您将编写一个存储过程来解析逗号分隔的列名并动态创建目标表,并解析值并加载它们。

不是最高效的数据加载方式,但如果您的文件很小,那么您应该没问题...

【讨论】:

    【解决方案2】:

    您可以使用文件枚举器类型的 Foreach 循环中的脚本任务来执行此操作。请注意,此示例旨在将数据发送到临时表,因为每列都定义为 VARCHAR(250)。您可能需要调整长度,250 只是用于测试目的。创建的表以数据来源的文件命名,您需要确保不存在具有这些名称的表,否则它们将被删除。如果您希望在已存在同名表时此操作失败,请删除第一个 SqlCommand.ExecuteNonQuery() 调用,这是执行此步骤的方法。在 Foreach 循环中,在索引 0 处添加一个变量来保存文件名,然后将此变量添加到脚本任务的 ReadOnlyVariables 字段中。在下面的示例中,此变量为 VariableWithFilePath

    using System.Data.SqlClient;
    using System.IO;
    using System.Collections.Generic;
    using System.Linq;
    
    
    string connstr = @"Data Source=YourServer;Initial Catalog=YourDatabase;Integrated Security=SSPI;";
    
    //get file path
    string fullFileName = Dts.Variables["User::VariableWithFilePath"].Value.ToString();
    
    //get only file name to be used when creating table
    string fileName = Path.GetFileNameWithoutExtension(fullFileName);
    
    DataTable dt = new DataTable();
    using (StreamReader sr = new StreamReader(fullFileName))
    {
        List<string> colNames = new List<string>();
    
        string firstLine = sr.ReadLine();
        string[] headers = firstLine.Split(',');
    
        foreach (string h in headers)
        {
            dt.Columns.Add(h);
            colNames.Add(h);
        }
    
        int columnCount = headers.Count();
        string line = sr.ReadLine();
    
        while (line != null)
        {
            string[] fields = line.Split(',');
    
            int currentLength = fields.Count();
            if (currentLength < columnCount)
            {
                //make sure fields from each row are kept together 
                while (currentLength < columnCount)
                {
                    line += sr.ReadLine();
                    currentLength = line.Split(',').Count();
                }
                fields = line.Split(',');
            }
    
            //load data table
            dt.Rows.Add(fields);
            line = sr.ReadLine();
        }
        string columns = string.Join(" VARCHAR(250), ", colNames);
    
        //command to drop table if it already exist
        string dropDDL = "IF (OBJECT_ID(N'DBO." + fileName + "') IS NOT NULL) DROP TABLE DBO." + fileName;
    
        //command to create new with same name as file
        string createDDL = "CREATE TABLE DBO." + fileName + " ( " + columns + " VARCHAR(250) )";
    
        using (SqlConnection conn = new SqlConnection(connstr))
        {
            SqlCommand sql = new SqlCommand();
            sql.Connection = conn;
            sql.CommandText = dropDDL;
    
            //drop table if exists
            conn.Open();
            sql.ExecuteNonQuery();
    
            //create table
            sql.CommandText = createDDL;
            sql.ExecuteNonQuery();
    
            //load SQL Server table from data table
            using (SqlBulkCopy blkCpy = new SqlBulkCopy(conn))
            {
                blkCpy.DestinationTableName = fileName;
                blkCpy.WriteToServer(dt);
            }
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-05
      • 1970-01-01
      • 2018-10-27
      相关资源
      最近更新 更多