C# 如何将数据表插入SQL Server数据库表?
我从某个Excel文件导入了数据,并将其保存到C# 如何将数据表插入SQL Server数据库表?,c#,sql-server,datatable,C#,Sql Server,Datatable,我从某个Excel文件导入了数据,并将其保存到数据表中。现在,我想将此信息保存在我的sqlserver数据库中 我在网上看到了很多信息,但我无法理解: 有人说逐行插入另一个建议的批量更新。。。等等:什么更好 我是否应该使用OLE或SQL Server对象(如dataAdapter或connection) 我需要从员工的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