如何唯一标识没有主键的表中的行

时间:2011-12-15 19:05:47

标签: sql-server

我从没有主键集的旧数据库/表导入超过600.000.000行,此表位于sql server 2005数据库中。我创建了一个工具,将这些数据导入到一个结构非常不同的新数据库中。问题是我想从任何原因恢复它停止的过程,如错误或网络错误。由于此表没有主键,我无法检查该行是否已导入。有谁知道如何识别每一行,以便我可以检查它是否已经导入?这个表有重复的行,我已经尝试计算所有列的哈希值,但由于重复的行而无法正常工作...

谢谢!

4 个答案:

答案 0 :(得分:5)

如果这是来自另一个数据库 - 一个在其上设置了标识的数据库,我会将这些行带入临时表。然后,您可以识别除id之外的所有其他数据相同的行,并在尝试将其放入生产表之前删除重复项。

答案 1 :(得分:1)

所以:你正在加载数十亿行数据,行无法唯一识别,负载可以(并且显然会)随时在任何时候被中断,并且你希望能够恢复这样的行从你离开的地方中断了负载,尽管从实际目的来看你无法确定你离开的地方。确定。

加载到包含其他标识列的表中会起作用,假设然而,无论何时启动数据加载,它始终从同一项开始并以相同的顺序加载项。效率极低,因为每次启动时都必须阅读每一个标记。

另一个笨重的选择是首先将您正在加载的数据分成可管理大小的块(可能是10,000,000行)。按块加载块,跟踪已加载的块。使用临时表,以便您知道并可以控制何时“完全处理”块。如果/当被打断时,你只会在中断时丢弃你正在处理的块,并恢复使用该块。

答案 2 :(得分:0)

对于重复的行,即使row_number()也会让你无处可去,因为这可能会在查询之间发生变化(由于MSSQL存储数据的方式)。您需要将其带入带有标识列的登陆表,或者将带有标识的新列添加到现有表(alter table oldTbl add column NewId int identity(1,1))。

您可以使用row_number(),然后在最后n行中退出,如果他们在新数据库中的计数超过了他们的数量,那么只使用一行就更直截了当着陆桌。

答案 3 :(得分:0)

选项1:可以删除重复项

尝试找到一个有点独特的字段组合。 (允许重复)并加入存储在目标表中的其余字段的哈希值。

假设一个表:

create table t_x(id int, name varchar(50), description varchar(100))
create table t_y(id int, name varchar(50), description varchar(100), hash varbinary(8000))

select * from t_x x 
where not exists(select * 
                 from t_y y 
                 where x.id = y.id 
                   and hashbytes('sha1', x.name + '~' + x.description) = y.hash) 

尝试加入尽可能多的字段的原因是为了减少在600.000.000条记录的数据集上真实的哈希冲突的可能性。

选项2:重复是重要的

如果您确实需要重复的行,则应在大表中添加唯一的id列。要以执行方式实现此目的,您应该执行以下步骤:

  • 更改表并添加uniqueidentifier或int字段
  • 使用newsequentialid()函数或row_number()
  • 更新表
  • 在此字段上创建索引
  • 将id字段添加到目标表。
  • 移完所有数据后,可以删除该字段。