C# 如何将数据表插入SQL Server数据库表?

C# 如何将数据表插入SQL Server数据库表?,c#,sql-server,datatable,C#,Sql Server,Datatable,我从某个Excel文件导入了数据,并将其保存到数据表中。现在,我想将此信息保存在我的sqlserver数据库中 我在网上看到了很多信息,但我无法理解: 有人说逐行插入另一个建议的批量更新。。。等等:什么更好 我是否应该使用OLE或SQL Server对象(如dataAdapter或connection) 我需要从员工的Excel文件中读取员工每周工时报告,并将其保存到保存所有报告的数据库表中(每周使用新记录更新数据库) Excel文件仅包含本周的报告。我建议您按照本文的建议进行批量插入: 在数据

我从某个Excel文件导入了数据,并将其保存到
数据表中。现在,我想将此信息保存在我的
sqlserver
数据库中

我在网上看到了很多信息,但我无法理解:

  • 有人说逐行插入另一个建议的批量更新。。。等等:什么更好
  • 我是否应该使用
    OLE
    SQL Server
    对象(如
    dataAdapter
    connection
  • 我需要从员工的Excel文件中读取员工每周工时报告,并将其保存到保存所有报告的数据库表中(每周使用新记录更新数据库)


    Excel文件仅包含本周的报告。

    我建议您按照本文的建议进行批量插入:

    在数据库中创建一个
    用户定义的表格类型

    CREATE TYPE [dbo].[MyTableType] AS TABLE(
        [Id] int NOT NULL,
        [Name] [nvarchar](128) NULL
    )
    
    并在
    存储过程中定义一个参数:

    CREATE PROCEDURE [dbo].[InsertTable]
        @myTableType MyTableType readonly
    AS
    BEGIN
        insert into [dbo].Records select * from @myTableType 
    END
    
    并将数据表直接发送到sql server:

    using (var command = new SqlCommand("InsertTable") {CommandType = CommandType.StoredProcedure})
    {
        var dt = new DataTable(); //create your own data table
        command.Parameters.Add(new SqlParameter("@myTableType", dt));
        SqlHelper.Exec(command);
    }
    

    要编辑存储过程中的值,可以声明具有相同类型的局部变量并将输入表插入其中:

    DECLARE @modifiableTableType MyTableType 
    INSERT INTO @modifiableTableType SELECT * FROM @myTableType
    
    然后,您可以编辑
    @modifiableTableType

    UPDATE @modifiableTableType SET [Name] = 'new value'
    

    如果这是您第一次保存数据表

    执行此操作(使用大容量复制)。确保没有PK/FK约束

    SqlBulkCopy bulkcopy = new SqlBulkCopy(myConnection);
    //I assume you have created the table previously
    //Someone else here already showed how  
    bulkcopy.DestinationTableName = table.TableName;
    try                             
    {                                 
        bulkcopy.WriteToServer(table);                            
    }     
        catch(Exception e)
    {
        messagebox.show(e.message);
    } 
    
    既然你已经有了基本的记录。您只需要将新记录与现有记录进行核对。你可以简单地做到这一点

    这将基本上从数据库中获取现有表

    DataTable Table = new DataTable();
    
    SqlConnection Connection = new SqlConnection("ConnectionString");
    //I assume you know better what is your connection string
    
    SqlDataAdapter adapter = new SqlDataAdapter("Select * from " + TableName, Connection);
    
    adapter.Fill(Table);
    
    然后将此表传递给此函数

    public DataTable CompareDataTables(DataTable first, DataTable second)
    {
        first.TableName = "FirstTable";
        second.TableName = "SecondTable";
    
        DataTable table = new DataTable("Difference");
    
        try
        {
            using (DataSet ds = new DataSet())
            {
                ds.Tables.AddRange(new DataTable[] { first.Copy(), second.Copy() });
    
                DataColumn[] firstcolumns = new DataColumn[ds.Tables[0].Columns.Count];
    
                for (int i = 0; i < firstcolumns.Length; i++)
                {
                    firstcolumns[i] = ds.Tables[0].Columns[i];
                }
    
                DataColumn[] secondcolumns = new DataColumn[ds.Table[1].Columns.Count];
    
                for (int i = 0; i < secondcolumns.Length; i++)
                {
                    secondcolumns[i] = ds.Tables[1].Columns[i];
                }
    
                DataRelation r = new DataRelation(string.Empty, firstcolumns, secondcolumns, false);
    
                ds.Relations.Add(r);
    
                for (int i = 0; i < first.Columns.Count; i++)
                {
                    table.Columns.Add(first.Columns[i].ColumnName, first.Columns[i].DataType);
                }
    
                table.BeginLoadData();
    
                foreach (DataRow parentrow in ds.Tables[0].Rows)
                {
                    DataRow[] childrows = parentrow.GetChildRows(r);
                    if (childrows == null || childrows.Length == 0)
                        table.LoadDataRow(parentrow.ItemArray, true);
                }
    
                table.EndLoadData();
    
            }
        }
    
        catch (Exception ex)
        {
            throw ex;
        }
    
        return table;
    }
    
    public DataTable CompareDataTables(DataTable第一,DataTable第二)
    {
    first.TableName=“FirstTable”;
    second.TableName=“SecondTable”;
    数据表=新数据表(“差异”);
    尝试
    {
    使用(数据集ds=新数据集())
    {
    AddRange(新数据表[]{first.Copy(),second.Copy()});
    DataColumn[]firstcolumns=新的DataColumn[ds.Tables[0].Columns.Count];
    for(int i=0;i
    这将返回一个新的DataTable,其中更新了更改的行。请确保正确调用该函数。DataTable first应该是最新的


    然后用这个新的数据表再次重复bulkcopy函数。

    我给出了一个非常简单的代码,我在解决方案中使用了它(我有与您相同的问题说明)

    我给了一个预定义的表名“abcd”(您必须注意,数据库中不存在使用此名称的表)。
    如果我的答案对你有效,请投我的票!!!!:)

    我发现,如果您的表有主键,则最好逐行添加到表中。一次插入整个表会在自动增量上产生冲突

    这是我的存储过程

    CREATE PROCEDURE dbo.usp_InsertRowsIntoTable
    @Year       int,
    @TeamName   nvarchar(50),
    AS
    INSERT INTO [dbo.TeamOverview]
    (Year,TeamName)
    VALUES (@Year, @TeamName);
    RETURN
    
    对于需要添加到表中的每一行,我都将此代码放入循环中:

    insertRowbyRowIntoTable(Convert.ToInt16(ddlChooseYear.SelectedValue), name);
    
    这是我的数据访问层代码:

            public void insertRowbyRowIntoTable(int ddlValue, string name)
        { 
            SqlConnection cnTemp = null;
            string spName = null;
            SqlCommand sqlCmdInsert = null;
    
            try
            {
                cnTemp = helper.GetConnection();
                using (SqlConnection connection = cnTemp)
                {
                    if (cnTemp.State != ConnectionState.Open)
                        cnTemp.Open();
                    using (sqlCmdInsert = new SqlCommand(spName, cnTemp))
                    {
                        spName = "dbo.usp_InsertRowsIntoOverview";
                        sqlCmdInsert = new SqlCommand(spName, cnTemp);
                        sqlCmdInsert.CommandType = CommandType.StoredProcedure;
    
                        sqlCmdInsert.Parameters.AddWithValue("@Year", ddlValue);
                        sqlCmdInsert.Parameters.AddWithValue("@TeamName", name);
    
                        sqlCmdInsert.ExecuteNonQuery();
    
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (sqlCmdInsert != null)
                    sqlCmdInsert.Dispose();
    
                if (cnTemp.State == ConnectionState.Open)
                    cnTemp.Close();
            }
    
        }
    

    根据我对这个问题的理解,这可以使用一个相当直接的解决方案。无论如何,下面是我建议的方法,此方法接收数据表,然后使用SQL语句插入数据库中的表。请注意,我的解决方案是使用MySQLConnection和MySqlCommand将其替换为SqlConnection和SqlCommand

    public void InsertTableIntoDB_CreditLimitSimple(System.Data.DataTable tblFormat)
        {
            for (int i = 0; i < tblFormat.Rows.Count; i++)
            {
    
                String InsertQuery = string.Empty;
    
                InsertQuery = "INSERT INTO customercredit " +
                              "(ACCOUNT_CODE,NAME,CURRENCY,CREDIT_LIMIT) " +
                              "VALUES ('" + tblFormat.Rows[i]["AccountCode"].ToString() + "','" + tblFormat.Rows[i]["Name"].ToString() + "','" + tblFormat.Rows[i]["Currency"].ToString() + "','" + tblFormat.Rows[i]["CreditLimit"].ToString() + "')";
    
    
    
                using (MySqlConnection destinationConnection = new MySqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ToString()))
                using (var dbcm = new MySqlCommand(InsertQuery, destinationConnection))
                {
                    destinationConnection.Open();
                    dbcm.ExecuteNonQuery();
                }
            }
        }//CreditLimit
    
    public void InsertTableIntoDB_CreditLimitSimple(System.Data.DataTable tblFormat)
    {
    对于(int i=0;i
    这不是一个好方法。如果其中一个数据行包含一个引号,会破坏SQL连接并引入SQL注入攻击的可能性。这是我自己的类,它是带有连接的帮助器类,在
    Exec
    方法中执行SQL命令,我使用它来简化我的代码。intresting,但是,如果要重新打开该数据表或编辑数据表中的值,我可以如何进行?要编辑存储过程中的值,可以声明一个具有相同类型的局部变量,并将输入表插入其中,即
    declare
    
            public void insertRowbyRowIntoTable(int ddlValue, string name)
        { 
            SqlConnection cnTemp = null;
            string spName = null;
            SqlCommand sqlCmdInsert = null;
    
            try
            {
                cnTemp = helper.GetConnection();
                using (SqlConnection connection = cnTemp)
                {
                    if (cnTemp.State != ConnectionState.Open)
                        cnTemp.Open();
                    using (sqlCmdInsert = new SqlCommand(spName, cnTemp))
                    {
                        spName = "dbo.usp_InsertRowsIntoOverview";
                        sqlCmdInsert = new SqlCommand(spName, cnTemp);
                        sqlCmdInsert.CommandType = CommandType.StoredProcedure;
    
                        sqlCmdInsert.Parameters.AddWithValue("@Year", ddlValue);
                        sqlCmdInsert.Parameters.AddWithValue("@TeamName", name);
    
                        sqlCmdInsert.ExecuteNonQuery();
    
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (sqlCmdInsert != null)
                    sqlCmdInsert.Dispose();
    
                if (cnTemp.State == ConnectionState.Open)
                    cnTemp.Close();
            }
    
        }
    
        //best way to deal with this is sqlbulkcopy 
        //but if you dont like it you can do it like this
        //read current sql table in an adapter
        //add rows of datatable , I have mentioned a simple way of it
        //and finally updating changes
    
        Dim cnn As New SqlConnection("connection string")        
        cnn.Open()
        Dim cmd As New SqlCommand("select * from  sql_server_table", cnn)
        Dim da As New SqlDataAdapter(cmd)       
        Dim ds As New DataSet()
        da.Fill(ds, "sql_server_table")
        Dim cb As New SqlCommandBuilder(da)        
    
        //for each datatable row
        ds.Tables("sql_server_table").Rows.Add(COl1, COl2)
    
        da.Update(ds, "sql_server_table")
    
    public void InsertTableIntoDB_CreditLimitSimple(System.Data.DataTable tblFormat)
        {
            for (int i = 0; i < tblFormat.Rows.Count; i++)
            {
    
                String InsertQuery = string.Empty;
    
                InsertQuery = "INSERT INTO customercredit " +
                              "(ACCOUNT_CODE,NAME,CURRENCY,CREDIT_LIMIT) " +
                              "VALUES ('" + tblFormat.Rows[i]["AccountCode"].ToString() + "','" + tblFormat.Rows[i]["Name"].ToString() + "','" + tblFormat.Rows[i]["Currency"].ToString() + "','" + tblFormat.Rows[i]["CreditLimit"].ToString() + "')";
    
    
    
                using (MySqlConnection destinationConnection = new MySqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ToString()))
                using (var dbcm = new MySqlCommand(InsertQuery, destinationConnection))
                {
                    destinationConnection.Open();
                    dbcm.ExecuteNonQuery();
                }
            }
        }//CreditLimit