我有一个小程序将csv文件导入sql server数据库 但当你按两次按钮或其他东西时,它会添加重复项。 我需要它,以便在有重复时跳过那一个。 如果有人可以帮我处理代码,那就太棒了。
编辑:我注意到有些人说我需要在工作时禁用按钮,而这是一个解决方案,我也想要,如果数据库中已有某些内容,它会跳过该部分,当它是相同的时候在csv文件中,如在数据库中。代码:
private void button1_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(@"server=localhost;Initial Catalog=klantbestand;Integrated Security=SSPI;");
string filepath = @"C:\clients TEST.csv";
StreamReader sr = new StreamReader(filepath);
string line = sr.ReadLine();
string[] value = line.Split(';');
DataTable dt = new DataTable();
DataRow row;
foreach (string dc in value)
{
dt.Columns.Add(new DataColumn(dc));
}
while (!sr.EndOfStream)
{
value = sr.ReadLine().Split(';');
if (value.Length == dt.Columns.Count)
{
row = dt.NewRow();
row.ItemArray = value;
dt.Rows.Add(row);
}
}
SqlBulkCopy bc = new SqlBulkCopy(con.ConnectionString, SqlBulkCopyOptions.TableLock);
bc.DestinationTableName = "GegevensCSV";
bc.BatchSize = dt.Rows.Count;
con.Open();
bc.WriteToServer(dt);
bc.Close();
con.Close();
}
答案 0 :(得分:3)
将数据批量加载到数据库表时,我遵循的一般原则是创建一个新的临时表(在导入期间仅暂时存在),将所有数据批量加载到其中,然后运行查询将该数据迁移到最终目标表中。之后,只需删除临时表。
这有一些好处:
答案 1 :(得分:1)
@AdaTheDev的回答是对的。但是还有另一种方法可以做到这一点。
如果在批量导入时出现重复插入问题,那么您也可以使用存储过程而不是使用批量复制功能来处理它。
在SQL Server中,对于2005年以后的版本,您可以使用“表值参数”,即您可以将整个表作为参数传递到存储过程并在服务器端对其进行操作。
如果通过存储过程参数将表传递到服务器端,则可以使用“合并命令”,其中merge命令是upsert命令。即,您可以以最安全,最快捷的方式插入以及更新或删除同一命令中所需的记录。
以下是有关该流程的一些详细信息:
步骤1:在SQL Server中创建表值参数;命令是:
CREATE TYPE [dbo].[TableTypeName] AS TABLE(
[ColumnName1] [DataType],
[ColumnName2] [DataType],
[ColumnName3] [DataType]
)
GO
这里“ColumnName1,2,3”是表列的名称,“DataType”是为列分配的sql server数据类型。
第2步:使用合并命令创建存储过程:
CREATE PROCEDURE [dbo].[ProcedureName]
@TableTypeName [dbo].[TableTypeName] READONLY
AS
BEGIN
DECLARE @InsertedRowsId TABLE
(
[InsertedRowId] [DataType] NOT NULL
);
DELETE FROM @InsertedRowsId;
BEGIN TRY
BEGIN TRANSACTION
-- Merge command
MERGE INTO [dbo].[TableName] AS [Target]
USING (
SELECT * FROM @TableTypeName
) AS [Source]
-- Candidate Keys: All the column(s) combination that makes the record(s) unique.
ON [Target].[ColumnName1] = [Source].[ColumnName1] -- Always false, ensures all rows copied
AND [Target].[ColumnName2] = [Source].[ColumnName2]
AND [Target].[ColumnName2] = [Source].[ColumnName2]
WHEN NOT MATCHED THEN
INSERT
(
[ColumnName1]
,[ColumnName1]
,[ColumnName1]
)
VALUES
(
[Source].[ColumnName1]
,[Source].[ColumnName1]
,[Source].[ColumnName1]
);
COMMIT TRANSACTION
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
END CATCH
END
第3步:现在是调用存储过程的最后一步。
Private void button1_Click(object sender, EventArgs e)
{
string connectionString = @"server=localhost;Initial Catalog=klantbestand;Integrated Security=SSPI;";
string filepath = @"C:\clients TEST.csv";
StreamReader sr = new StreamReader(filepath);
string line = sr.ReadLine();
string[] value = line.Split(';');
DataTable dt = new DataTable();
DataRow row;
foreach (string dc in value)
{
dt.Columns.Add(new DataColumn(dc));
}
while (!sr.EndOfStream)
{
value = sr.ReadLine().Split(';');
if (value.Length == dt.Columns.Count)
{
row = dt.NewRow();
row.ItemArray = value;
dt.Rows.Add(row);
}
}
if (dt.Rows.Count>0) {
using (SqlConnection connection = new SqlConnection(connectionString)) {
connection.Open();
using (SqlCommand command = connection.CreateCommand()) {
command.CommandText = "dbo.ProcedureName";
command.CommandType = CommandType.StoredProcedure;
SqlParameter parameter;
parameter = command.Parameters.AddWithValue("@TableTypeName", dt);
parameter.SqlDbType = SqlDbType.Structured;
parameter.TypeName = "dbo.TableTypeName";
command.ExecuteNonQuery();
}
}
}
}
通过这种方式,您可以批量导入数据,而无需重复记录。 甚至,如果需要,您可以记录插入或异常详细信息。