简体   繁体   English

将缺少列的 CSV 导入 MS SQL 服务器表

[英]Import CSV with missing columns into MS SQL Server table

Suppose I got a csv file like this:假设我有一个像这样的 csv 文件:

field1 field3
0      1
1      2

The corresponding table looks like this:对应的表格如下所示:

field1 field2 field3
null   null   null
...    ...    ...

Suppose all the fields are nullable, how could I import the csv file into the table?假设所有字段都可以为空,我如何将 csv 文件导入表中? I know I could BULK INSERT with a formatter, but I cannot generate formatter by bcp cuz the connection to the local SQL server failed (weird?) Is there any better way to solve this problem?我知道我可以使用格式化程序批量BULK INSERT ,但我无法通过bcp生成格式化程序,因为与本地 SQL 服务器的连接失败(奇怪?)有没有更好的方法来解决这个问题?

You could create a staging table with only the columns that you have in your data csv file, and then use BCP to load data into that.您可以创建一个仅包含数据 csv 文件中的列的临时表,然后使用 BCP 将数据加载到其中。 After that use INSERT INTO...SELECT..FROM to load data to your target table.之后使用INSERT INTO...SELECT..FROM将数据加载到目标表。 see this answer for more details.有关更多详细信息,请参阅此答案

Working with csv/txt delimited files can be tricky when moving them over into a SQL Server table.将 csv/txt 分隔文件移动到 SQL 服务器表中时,使用它们可能会很棘手。 I've had users mess up columns or have too many columns etc. My solution was to first use stream reader to read the file then add the header row into an array, placing the data itself into its own array.我让用户弄乱了列或列太多等。我的解决方案是首先使用 stream 读取器读取文件,然后将 header 行添加到数组中,将数据本身放入自己的数组中。 Then I loop through the header array and add each value into a column from a empty DataTable.然后我循环遍历 header 数组并将每个值添加到空 DataTable 的列中。 So now I have a data table that holds the header names (which represent the Column names in SQL Server) and another data table holding the actual data.所以现在我有一个包含 header 名称(代表 SQL 服务器中的列名)的数据表和另一个包含实际数据的数据表。 Then query the SQL server Table to get a dictionary list of the Column names:然后查询SQL服务器表,得到一个列名的字典列表:

        Dictionary<int, string> SQLTableColNamesDict = new Dictionary<int, string>();

        string Command = " SELECT COLUMN_NAME, ORDINAL_POSITION FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'table name' ";
        using (SqlConnection Connection = new SqlConnection(sqlconnectionstring))
        {
            Connection.Open();
            using (SqlCommand cmd = new SqlCommand(Command, Connection))
            {
                using (SqlDataReader reader = cmd.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        SQLTableColNamesDict.Add((int)reader[1], (string)reader[0].ToString().ToUpper());
                    }
                }
            }
        }

Then loop through the header array and see if the dictionary list matches the header value, if I have a match use Bulk Copy to map the Column.然后遍历 header 数组并查看字典列表是否与 header 值匹配,如果我有匹配项,请使用批量复制到 map 列。

             using (SqlBulkCopy bulkCopy = new SqlBulkCopy(sqlconnectionstring))
        {
            bulkCopy.DestinationTableName = SQLdestinationTable;

            bulkCopy.BatchSize = dtWithColNames.Rows.Count;

            foreach (string columnFromFile in firstRowHeaderFromFileArray)
            {



                string DesintationOrdinalPostion = "";
                string DesintationColName = "";

                if (SQLTableColNamesDict.ContainsValue(columnFromFile.ToUpper()))
                {
                    DesintationOrdinalPostion = SQLTableColNamesDict.First(item => item.Value == columnFromFile.ToUpper()).Key.ToString();

                    DesintationColName = SQLTableColNamesDict.First(item => item.Value == columnFromFile.ToUpper()).Value.ToString();

                }


                if (DesintationOrdinalPostion != "")
                // if (colFound != null)
                {
                    SqlBulkCopyColumnMapping col = new SqlBulkCopyColumnMapping();


                    // col.SourceColumn = columnFromFile;

                    col.SourceColumn = DesintationColName;

                    col.DestinationOrdinal = Convert.ToInt32(DesintationOrdinalPostion);
                    col.DestinationColumn = columnFromFile.ToUpper();


                    bulkCopy.ColumnMappings.Add(col);


                }

            }

Then finally do the bulk copy然后最后做批量复制

                 int recordCount = 0;
            recordCount = dtWithColNames.Rows.Count;

            // Write from the source to the destination.
            try
            {
                bulkCopy.WriteToServer(dtWithColNames);



            }
            catch (Exception error)
            {

            }
            finally
            {

                bulkCopy.Close();

            }

This should allow the transfer to work even if the csv file is perhaps malformed with extra columns and only take in valid columns which match your SQL table.这应该允许传输工作,即使 csv 文件可能带有额外列的格式错误并且只接受与您的 SQL 表匹配的有效列。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM