C# 避免在数据库中添加重复项的最佳方法
我有一个包含三列的SQL Server表: 表1C# 避免在数据库中添加重复项的最佳方法,c#,sql-server,hashset,C#,Sql Server,Hashset,我有一个包含三列的SQL Server表: 表1 col1 int col2 int col3 string 我为所有三列(col1、col2、col3) 现在,我有一个.csv文件,我想在这个表中添加记录,*.csv文件可以有重复的记录 我已经在上面的场景中搜索了各种避免重复的选项。下面是三个对我很有效的选项。请看一看,并就每种方法的优缺点提出一些想法,以便我可以选择最好的方法 选项#1: 首先避免重复,即从csv文件向列表中添加对象时。我为此使用了HashSet,并覆盖了以下类型T的方法:
col1 int
col2 int
col3 string
我为所有三列(col1、col2、col3)
现在,我有一个.csv文件,我想在这个表中添加记录,*.csv文件可以有重复的记录
我已经在上面的场景中搜索了各种避免重复的选项。下面是三个对我很有效的选项。请看一看,并就每种方法的优缺点提出一些想法,以便我可以选择最好的方法
选项#1:
首先避免重复,即从csv文件向列表中添加对象时。我为此使用了HashSet
,并覆盖了以下类型T的方法:
public override int GetHashCode()
{
return col1.GetHashCode() + col2.GetHashCode() + col3.GetHashCode();
}
public override bool Equals(object obj)
{
var other = obj as T;
if (other == null)
{
return false;
}
return col1 == other.col1
&& col2 == other.col2
&& col3 == other.col3;
}
选项2
具有列表
而不是哈希集
将所有对象添加到列表后删除重复项
虽然我没有比较它们的运行时间,但我更喜欢选项#1,因为我将删除重复项作为第一步-因此只需要按照需要继续
请分享你的观点,这样我可以选择最好的
非常感谢 我喜欢选项1:HashSet
提供了一种在发送到数据库之前避免重复的快速方法。您应该实现更好的GetHashCode
,例如,从
但有一个问题:如果表中已经包含可能与CSV重复的数据,该怎么办?为了使一个简单的HashSet
真正起作用,您必须首先复制整个表。您可以这样做,但要解决这个问题,我可能会将选项1与临时表和insert语句配对,如:
通过这种组合,可以最大限度地减少从数据库传输到数据库的数据量。另一种解决方案是在创建/重建索引时使用IGNORE\u DUP\u KEY={ON | OFF}
选项。此解决方案将防止插入重复行时出错。相反,SQL Server将生成警告:重复密钥被忽略。
CREATE TABLE dbo.MyTable (Col1 INT, Col2 INT, Col3 INT);
GO
CREATE UNIQUE INDEX IUN_MyTable_Col1_Col2_Col3
ON dbo.MyTable (Col1,Col2,Col3)
WITH (IGNORE_DUP_KEY = ON);
GO
INSERT dbo.MyTable (Col1,Col2,Col3)
VALUES (1,11,111);
INSERT dbo.MyTable (Col1,Col2,Col3)
SELECT 1,11,111 UNION ALL
SELECT 2,22,222 UNION ALL
SELECT 3,33,333;
INSERT dbo.MyTable (Col1,Col2,Col3)
SELECT 2,22,222 UNION ALL
SELECT 3,33,333;
GO
/*
(1 row(s) affected)
(2 row(s) affected)
Duplicate key was ignored.
*/
SELECT * FROM dbo.MyTable;
/*
Col1 Col2 Col3
----------- ----------- -----------
1 11 111
2 22 222
3 33 333
*/
注意:因为如果您尝试使用ALTER index更改索引选项,则会有一个唯一的约束
ALTER INDEX IUN_MyTable_Col1_Col2_Col3
ON dbo.MyTable
REBUILD WITH (IGNORE_DUP_KEY = ON)
您将得到以下错误:
Msg 1979, Level 16, State 1, Line 1
Cannot use index option ignore_dup_key to alter index 'IUN_MyTable_Col1_Col2_Col3' as it enforces a primary or unique constraint.`
因此,如果您选择此解决方案,选项如下:
1) 创建另一个唯一索引并删除唯一约束(此选项将需要更多存储空间,但唯一索引/约束将始终处于活动状态)或
2) 删除唯一约束并使用(IGNORE_DUP_KEY=ON)
选项创建一个唯一索引(我不建议使用最后一个选项)。从csv获取数据并将其批量插入没有唯一约束的临时表不是更有效吗,使用sql删除重复项,然后将没有重复项的数据移动到实际的最终表中?如果使用选项1,我可能会将GetHashCode
更改为将属性乘以素数,就像在这个废弃选项1中一样-使用哈希代码不能保证唯一性。@DStanley哈希代码本身不能保证唯一性,但是,如上所述使用的HashSet
,正是他想要做的。@iniki您考虑过使用SSIS吗?在数据流任务中,您可以将错误行重定向到某些输出或忽略它们。这样,只会插入第一个唯一的行。
CREATE TABLE dbo.MyTable (Col1 INT, Col2 INT, Col3 INT);
GO
CREATE UNIQUE INDEX IUN_MyTable_Col1_Col2_Col3
ON dbo.MyTable (Col1,Col2,Col3)
WITH (IGNORE_DUP_KEY = ON);
GO
INSERT dbo.MyTable (Col1,Col2,Col3)
VALUES (1,11,111);
INSERT dbo.MyTable (Col1,Col2,Col3)
SELECT 1,11,111 UNION ALL
SELECT 2,22,222 UNION ALL
SELECT 3,33,333;
INSERT dbo.MyTable (Col1,Col2,Col3)
SELECT 2,22,222 UNION ALL
SELECT 3,33,333;
GO
/*
(1 row(s) affected)
(2 row(s) affected)
Duplicate key was ignored.
*/
SELECT * FROM dbo.MyTable;
/*
Col1 Col2 Col3
----------- ----------- -----------
1 11 111
2 22 222
3 33 333
*/
ALTER INDEX IUN_MyTable_Col1_Col2_Col3
ON dbo.MyTable
REBUILD WITH (IGNORE_DUP_KEY = ON)
Msg 1979, Level 16, State 1, Line 1
Cannot use index option ignore_dup_key to alter index 'IUN_MyTable_Col1_Col2_Col3' as it enforces a primary or unique constraint.`