如何将数据表插入到SQL Server数据库表中?
我已经从一些Excel文件导入数据,并将其保存到数据表中。 现在我想将这些信息保存在我的SQL Server
数据库中。
我在网上看到很多信息,但是我不明白:
- 有人说逐行插入另一个build议的批量更新…等:有什么更好的?
- 我应该使用
OLE
还是SQL Server
对象(如dataAdapter
或connection
)?
我需要从他的Excel文件中读取员工每周工时报告,并将其保存到保存所有报告的数据库表(每周更新新数据库)。
Excel文件只包含当前一周的报告。
在您的数据库中创build一个User-Defined TableType
:
CREATE TYPE [dbo].[MyTableType] AS TABLE( [Id] int NOT NULL, [Name] [nvarchar](128) NULL )
并在您的Stored Ptocedure
定义一个参数:
CREATE PROCEDURE [dbo].[InsertTable] @myTableType MyTableType readonly AS BEGIN insert into [dbo].Records select * from @myTableType END
并将您的DataTable
直接发送到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); }
要编辑存储过程中的值,可以声明一个具有相同types的本地variables并将input表插入到该variables中:
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); }
现在你已经有了一个基本的logging。 而你只是想检查现有的新纪录。 你可以简单地做到这一点。
这将基本上从数据库中取现有的表
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; }
这将返回一个新的DataTable更新的更改行。 请确保您正确地调用该function。 DataTable首先应该是最新的。
然后用这个新的数据表重复批量复制function。
我给出了一个非常简单的代码,我在我的解决scheme中使用(我有和你一样的问题陈述)
SqlConnection con = connection string ; //new SqlConnection("Data Source=.;uid=sa;pwd=sa123;database=Example1"); con.Open(); string sql = "Create Table abcd ("; foreach (DataColumn column in dt.Columns) { sql += "[" + column.ColumnName + "] " + "nvarchar(50)" + ","; } sql = sql.TrimEnd(new char[] { ',' }) + ")"; SqlCommand cmd = new SqlCommand(sql, con); SqlDataAdapter da = new SqlDataAdapter(cmd); cmd.ExecuteNonQuery(); using (var adapter = new SqlDataAdapter("SELECT * FROM abcd", con)) using(var builder = new SqlCommandBuilder(adapter)) { adapter.InsertCommand = builder.GetInsertCommand(); adapter.Update(dt); // adapter.Update(ds.Tables[0]); (Incase u have a data-set) } con.Close();
我已经给出了一个预定义的表名作为“abcd”(你必须注意在这个数据库中不存在这个名字的表)。 请投我的答案,如果它适合你! 🙂
我build议你去这个文章中build议的批量插入 : 批量插入数据使用C#DataTable和SQL服务器OpenXML函数
public bool BulkCopy(ExcelToSqlBo objExcelToSqlBo, DataTable dt, SqlConnection conn, SqlTransaction tx) { int check = 0; bool result = false; string getInsert = ""; try { if (dt.Rows.Count > 0) { foreach (DataRow dr in dt.Rows) { if (dr != null) { if (check == 0) { getInsert = "INSERT INTO [tblTemp]([firstName],[lastName],[Father],[Mother],[Category]" + ",[sub_1],[sub_LG2])"+ " select '" + dr[0].ToString() + "','" + dr[1].ToString() + "','" + dr[2].ToString() + "','" + dr[3].ToString() + "','" + dr[4].ToString().Trim() + "','" + dr[5].ToString().Trim() + "','" + dr[6].ToString(); check += 1; } else { getInsert += " UNION ALL "; getInsert += " select '" + dr[0].ToString() + "','" + dr[1].ToString() + "','" + dr[2].ToString() + "','" + dr[3].ToString() + "','" + dr[4].ToString().Trim() + "','" + dr[5].ToString().Trim() + "','" + dr[6].ToString() ; check++; } } } result = common.ExecuteNonQuery(getInsert, DatabasesName, conn, tx); } else { throw new Exception("No row for insertion"); } dt.Dispose(); } catch (Exception ex) { dt.Dispose(); throw new Exception("Please attach file in Proper format."); } return result; }
//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")
我发现如果你的表有一个主键,那么最好逐行添加到表中。 一次插入整个表会在自动增量上产生冲突。
这是我存储的Proc
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(); } }
从我对这个问题的理解,这可以使用一个相当直接的解决scheme。以下任何一种方法我build议,这种方法需要一个数据表,然后使用SQL语句插入到数据库中的表。请注意,我的解决scheme正在使用MySQLConnection和MySqlCommand将其replace为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