【问题标题】:How can we import excel file to Sql server table where excel table columns are not in order as Sql table我们如何将 excel 文件导入 Sql server 表,其中 excel 表列不按 Sql 表顺序排列
【发布时间】:2020-05-07 20:06:57
【问题描述】:

我有一个 Excel 文件,其工作表名称与 SQL 表名称相同,但列映射失败,因为两者具有相同的列但列的顺序不同,请帮助我。

【问题讨论】:

    标签: c# .net sql-server


    【解决方案1】:

    已编辑:最后添加了另一个示例。

    实现您所要求的许多方法之一是将工作表作为数据表导入 c#,然后使用 SqlBulkCopy (SqlBulkCopy (MSDN)) 插入数据。这种方法更适合大文件,因为 SqlBulkCopy 使用批量插入命令。

    对于第一步(将文件导入为数据表),您有许多选项,例如使用 OLEDB 用于 xls 或 xlsx(您可以使用我的示例或其他示例,例如 this linkthis),使用第三方库,例如作为easyxls

    using System;
    using System.Drawing;
    using System.Windows.Forms;
    using Excel = Microsoft.Office.Interop.Excel; 
    
    namespace WindowsApplication1
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                try
                {
                    System.Data.OleDb.OleDbConnection MyConnection ;
                    System.Data.DataSet DtSet ;
                    System.Data.OleDb.OleDbDataAdapter MyCommand ;
                    MyConnection = new System.Data.OleDb.OleDbConnection("provider=Microsoft.Jet.OLEDB.4.0;Data Source='c:\\csharp.net-informations.xls';Extended Properties=Excel 8.0;");
                    MyCommand = new System.Data.OleDb.OleDbDataAdapter("select * from [Sheet1$]", MyConnection);
                    MyCommand.TableMappings.Add("Table", "TestTable");
                    DtSet = new System.Data.DataSet();
                    MyCommand.Fill(DtSet);
                    dataGridView1.DataSource = DtSet.Tables[0];
                    MyConnection.Close();
                }
                catch (Exception ex)
                {
                    MessageBox.Show (ex.ToString());
                }
            }
       }
    }
    

    在第二步之后,您可以使用带有列映射的 SQLBulkCopy 将 dataTable 列映射到您的数据库表列。

    using System.Data.SqlClient;
    
    class Program
    {
        static void Main()
        {
            string connectionString = GetConnectionString();
            // Open a sourceConnection to the AdventureWorks database.
            using (SqlConnection sourceConnection =
                       new SqlConnection(connectionString))
            {
                sourceConnection.Open();
    
                // Perform an initial count on the destination table.
                SqlCommand commandRowCount = new SqlCommand(
                    "SELECT COUNT(*) FROM " +
                    "dbo.BulkCopyDemoDifferentColumns;",
                    sourceConnection);
                long countStart = System.Convert.ToInt32(
                    commandRowCount.ExecuteScalar());
                Console.WriteLine("Starting row count = {0}", countStart);
    
                // Get data from the source table as a SqlDataReader.
                SqlCommand commandSourceData = new SqlCommand(
                    "SELECT ProductID, Name, " +
                    "ProductNumber " +
                    "FROM Production.Product;", sourceConnection);
                SqlDataReader reader =
                    commandSourceData.ExecuteReader();
    
                // Set up the bulk copy object.
                using (SqlBulkCopy bulkCopy =
                           new SqlBulkCopy(connectionString))
                {
                    bulkCopy.DestinationTableName =
                        "dbo.BulkCopyDemoDifferentColumns";
    
                    // Set up the column mappings by name.
                    SqlBulkCopyColumnMapping mapID =
                        new SqlBulkCopyColumnMapping("ProductID", "ProdID");
                    bulkCopy.ColumnMappings.Add(mapID);
    
                    SqlBulkCopyColumnMapping mapName =
                        new SqlBulkCopyColumnMapping("Name", "ProdName");
                    bulkCopy.ColumnMappings.Add(mapName);
    
                    SqlBulkCopyColumnMapping mapMumber =
                        new SqlBulkCopyColumnMapping("ProductNumber", "ProdNum");
                    bulkCopy.ColumnMappings.Add(mapMumber);
    
                    // Write from the source to the destination.
                    try
                    {
                        bulkCopy.WriteToServer(reader);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }
                    finally
                    {
                        // Close the SqlDataReader. The SqlBulkCopy
                        // object is automatically closed at the end
                        // of the using block.
                        reader.Close();
                    }
                }
    
                // Perform a final count on the destination 
                // table to see how many rows were added.
                long countEnd = System.Convert.ToInt32(
                    commandRowCount.ExecuteScalar());
                Console.WriteLine("Ending row count = {0}", countEnd);
                Console.WriteLine("{0} rows were added.", countEnd - countStart);
                Console.WriteLine("Press Enter to finish.");
                Console.ReadLine();
            }
        }
    
        private static string GetConnectionString()
            // To avoid storing the sourceConnection string in your code, 
            // you can retrieve it from a configuration file. 
        {
            return "Data Source=(local); " +
                " Integrated Security=true;" +
                "Initial Catalog=AdventureWorks;";
        }
    }
    

    SqlBulkCopy 用法的另一个例子:

    public bool CopyTransactionDataToTable(DataTable Dt, long ProductID)
        {
    
        try
        {
            SqlBulkCopy copy = new SqlBulkCopy(Adapter.GetActiveConnection().ConnectionString);
            Collection = mapping.LoadMappedNameEntityByProductID(ProductID);
    
            copy.ColumnMappings.Add("ProductID", "ProductID");
            copy.ColumnMappings.Add("ResellerID", "ResellerID");
            copy.ColumnMappings.Add("Status", "Status");
            copy.ColumnMappings.Add("PK_ID", "TxID");
            copy.DestinationTableName = "TBLProdect";
            copy.BulkCopyTimeout = ConfigurationSettings.AppSettings.Get(UIConstants.SQLTimeOut).ToInt32();
            copy.WriteToServer(Dt);
            Adapter.CommandTimeOut = copy.BulkCopyTimeout;
            return true;
        }
        catch (Exception ex)
        {
            Log.Error(ex);
            return false;
        }
    }
    

    【讨论】:

    • 谢谢,但我在 Sql db 中有 13 个 excel 工作表和 13 个表...需要从 Excel 文件动态地将匹配列的数据导入 SQL Server 表,不能给出列的名称跨度>
    • 不客气。所以我没有发现问题!你如何决定excel文件的哪一列应该放在哪里?请举例说明您的文件结构和表架构。
    • 我在下面使用了带有列映射的 sql bulkcopy 代码,但是如果不匹配确切的列并且列应该按顺序排列,则它不起作用。
    • using (SqlBulkCopy sqlBulk = new SqlBulkCopy(SqlMapSession.Connection.ConnectionString)) { // 目标表名。表名是工作表名减去任何 $ sqlBulk.DestinationTableName = dtSheetRecords.TableName.Replace("$", ""); foreach(dtSheetRecords.Columns 中的 var 列){ sqlBulk.ColumnMappings.Add(column.ToString(), column.ToString()); } sqlBulk.WriteToServer(dtSheetRecords); }
    • 我为您编写的 sn-p 代码来自 MSDN(从数据库名称和代码结构中可以明显看出)。我还将添加包含在我的一个项目中的部分代码。
    【解决方案2】:

    您没有说明您是否希望重复或编程等 - 但其他两个选项是使用 SQL Server 数据导入/导出向导

    https://msdn.microsoft.com/en-us/library/ms141209.aspx

    另一种选择是使用 SQL Server Integration Services (SSIS)

    http://www.sqlshack.com/using-ssis-packages-import-ms-excel-data-database/

    【讨论】:

    • 对不起,托尼,但我希望通过编程来做到这一点,挑战是程序只有在确切的源和列位置和编号匹配时才工作,即整个格式,但如果任何列的顺序不匹配或如果 excel 的列比 db 表多,反之亦然,则失败
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-27
    • 2010-10-03
    • 2015-12-05
    • 1970-01-01
    相关资源
    最近更新 更多