为了避免解释不清我的问题,我会尽量提供更多信息。
我正在创建一个批量上传过程,可以将数据插入到两个表中。这两个表大致如下。TableA
是一个自引用表格,允许N级引用。
Parts (self-referencing table)
--------
PartId (PK Int Non-Auto-Incrementing)
DescriptionId (Fk)
ParentPartId
HierarchyNode (HierarchyId)
SourcePartId (VARCHAR(500) a unique Part Id from the source)
(other columns)
Description
--------
DescriptionId (PK Int Non-Auto-Incrementing)
Language (PK either 'EN' or 'JA')
DescriptionText (varchar(max))
(我还应该注意,有其他表将引用我们的
PartID
,但目前我不会涉及这些。)在
Description
中,Description
和Language
的组合将是唯一的,但实际的`DescriptionID`将始终至少有两个实例。现在,对于批量上传过程,我创建了两个分段表,看起来很像
Parts
和Description
,但没有任何PK、索引等。它们是Parts_Staging
和Description_Staging
。在
Parts_Staging
中,有一个额外的列,包含层次结构节点字符串,这是这种格式的HierarchyNode:/1/2/3/
等。然后当数据从_Staging表复制到实际表时,我使用CAST(Source.Column AS hierarchyid)
。由于在两个表之间共享的ID的复杂性,自引用ID和
Parts
中的层次结构ID以及要插入的行数(可能在10万以上),我决定100%先在C#模型中编译所有数据,包括PK ID。所以在C#中,该过程如下:1.查询两个表的MAX ID 2.使用这些Max ID,编译两个表的所有数据的完整模型(包括层次结构/1/2/3/) 3.对两个_Staging表进行批量插入 4.触发一个SP,将两个_Staging表中的非重复数据复制到实际表中。(这是
CAST(Source.Column AS hierarchyid)
发生的地方)。我们正在导入许多零件手册,单个零件可能会在多本书中复制。我们需要删除重复项。在第4步中,通过检查
Parts
表中的SourcePartId
和Description
表中的DescriptionText
中的Description
来除去重复项。整个过程运行得很好!而且最重要的是,它非常快。但是,如果您仔细阅读此内容(我感谢您),则已经注意到一个明显的问题。
如果同时进行多个进程(这绝对会发生!),那么存在非常真实的风险,即ID混乱并且数据变得非常损坏。Process1可以执行
GET MAX ID
查询,并在完成之前,Process2也可以执行GET MAX ID
查询,因为Process1实际上还没有写入表,所以它将获得相同的ID。我最初打算使用SEQUENCE对象,而最初的计划似乎非常出色。但在测试中它瓦解了,因为同一数据有可能会被处理多次,并且在从_Staging表复制到最终表时被忽略。在这种情况下,SEQUENCE数字将已经被占用和使用,导致ID中存在巨大的间隙。虽然这不是致命缺陷,但我们宁愿避免这个问题。
所以...这是一个很长的背景信息,要问这个实际问题。我想做的是:
- 锁定两个相关的表
- 按上述步骤执行步骤1-4
- 解锁这两个表。
我的问题是:1)这是最好的方法吗?2)如何在表上放置排他锁?
谢谢!