如何正确避免在 SQL 没有主键的服务器数据表中插入重复行?

How to properly avoid insert duplicate rows in SQL Server data tables which don't have any PK?

我在 C# 中使用 SqlBulkCopy class 将数据从一个 SQL 服务器数据库快速复制到另一个。数据库在不同的服务器上,它们的数据表没有任何PK,所以过程变得更加复杂。

问题是我对来自原始数据库的 select 数据使用的查询得到了重复的行,并且 SqlBulkCopy 无法避免在目标数据库中插入重复的记录。

我不能使用 SELECT *,因为它会抛出 OutOfMemoryException,所以我使用 SELECT TOP X * 并将该数据加载到 DataTable。在每个 Datatable 中,我可以使用 C# 删除重复记录,但是当我 select 下一个 TOP X 时,第一行 selected 可能等于previous DataTable 并且已经插入到目标数据库中。 DataTable变量一直不变,重新加载!

我想避免在不创建 PK 的情况下插入重复记录,因为它不适用于我的情况。我真的需要使用 SqlBulkCopy 因为快速复制是一项系统要求。有什么建议吗?提前致谢!

不要使用 C#。

您可以在 SSMS 中右键单击您的原始数据库并选择 "Tasks",然后选择 "Generate Scripts"。选择您想要的 table 并使用向导生成您的插入脚本。然后 运行 这些在你的第二个数据库上。

如果需要重复此操作,您可以设置 Linked Server between your two SQL Server instances, and then write an insert statement from one to the other in a Stored Procedure. You can then run this stored procedure whenever you need, or call it from C#

如果您希望它定期 运行,您可以设置一个 Job on the database

您是否考虑过将第一个数据库中的行复制到磁盘而不是内存中的文件中?然后,您将能够一次性获得所有这些,而无需使用 select top X * 进行批量处理。一旦数据在磁盘上,就可以对其进行排序——甚至可能使用处理大文件的 Unix sort 实现——并删除重复记录。

如果您想删除重复项,那么在某些时候您将需要将所有数据放在一个地方,然后对其进行排序或对其建立索引。它可以在第一个数据库、内存、磁盘或第二个数据库中。您不想在任何一个数据库中建立索引是有原因的,并且内存中没有空间容纳所有数据,因此似乎只能将其假脱机到磁盘作为唯一的选择。

不过,就我个人而言,我会非常认真地考虑制作主键。虽然你说它不适用,但它可能是值得的,只是为了帮助数据加载。