我有一个包含三列的SQL Server表:
表1
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
List<T>
代替HashSet<T>
。
在将所有对象添加到List<T>
List<T> distinctObjects = allObjects
.GroupBy(x => new {x.col1, x.col2, x.col3})
.Select(x => x.First()).ToList();
选项#3
在将所有对象添加到DataTable
后删除重复项。
public static DataTable RemoveDuplicatesRows(DataTable dataTable)
{
IEnumerable<DataRow> uniqueRows = dataTable.AsEnumerable().Distinct(DataRowComparer.Default);
DataTable dataTable2 = uniqueRows.CopyToDataTable();
return dataTable2;
}
虽然我还没有比较他们的运行时间,但我更喜欢选项#1,因为我正在删除重复项作为第一步 - 所以只需要按照要求进行操作。
请分享您的观点,以便我选择最好的观点。
非常感谢!
答案 0 :(得分:5)
我喜欢选项1:HashSet<T>
提供了一种避免重复的快速方法,然后再将它们发送到数据库。您应该实施更好的GetHashCode
,例如使用来自What is the best algorithm for an overridden System.Object.GetHashCode?
但是有一个问题:如果表中已包含可能与您的CSV重复的数据,该怎么办?你必须首先复制整个表格才能使一个简单的HashSet
真正起作用。你可以这样做,但为了解决这个问题,我可能会将选项1与临时表和Skip-over/ignore duplicate rows on insert的插入语句配对:
INSERT dbo.Table1(col1, col2, col3)
SELECT col1, col2, col3
FROM dbo.tmp_holding_Table1 AS t
WHERE NOT EXISTS (SELECT 1 FROM dbo.Table1 AS d
WHERE col1 = t.col1
AND col2 = t.col2
AND col3 = t.col3);
通过这种组合,可以最大限度地减少传输到数据库或从数据库传输的数据量。
答案 1 :(得分:0)
创建/重建索引时,另一个解决方案可能是IGNORE_DUP_KEY = { ON | OFF }
选项。此解决方案将防止插入重复行时出错。相反,SQL Server将生成警告:Duplicate key was ignored.
。
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
更改索引选项,则因为您具有UNIQUE约束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)创建另一个UNIQUE索引并删除UNIQUE约束(此选项将需要更多存储空间,但将始终是一个独立的UNIQUE索引/约束)或
2)删除UNIQUE约束并使用WITH (IGNORE_DUP_KEY = ON)
选项创建一个UNIQUE索引(我不建议使用最后一个选项)。