2

我有一个带有“ID”列的数据库。每当数据库有新条目时,我都会从数据库中获取最后一个 ID,增加值,然后在 Insert 语句中使用它。

编辑:我需要在多个插入语句中使用 ID。我将从主表中获取此 ID,并使用此 ID 将值插入相关表中。

    NextID = Select Max(ID) + 1 From Table

    INSERT INTO Table1(ID, Col1, Col2...) Values(NextId, Value1, Value2...)

    INSERT INTO Table2 (ID,col1,col2....) Values (NextID, Value1, Value2...)

我不知道这是否是一个好方法,因为我知道会有并发问题。当我的应用程序尝试读取 NextID 时,有可能该应用程序的另一个实例也尝试读取相同的值,因此可能会出现并发问题。

有没有适当的方法来处理这种情况?我的意思是有一些方法可以设置数据库隔离级别。对于这种情况,这将是适当的隔离级别。

此外,如果有人可以建议我用另一种方法来手动维护和增加数据库中的 ID,我也愿意接受。

如果这些信息还不够,请告诉我您需要什么。

我正在使用带有 VB 和 MS Sql Server 2008 的 ASP.Net。我不想使用 SQL Server 的内置“身份”。

4

3 回答 3

3

获取下一个 ID 的唯一方法是实际插入行,并使用标识。其他一切都会失败。因此,您必须首先插入父表:

begin transaction;
insert into Table (col1, col2, col3) values (value1, value2, value3);
set @Id = scope_identity();
insert into Table1(ID, col1, col2) values (@Id, ...);
insert into Table3(ID, col1, col2) values (@Id, ...);
commit;

这是原子和并发安全的。

我不想使用 SQL Server 的内置“身份”。

tl;博士。除非您能明确说明原因,否则您“想要”的东西无关紧要。你可以正确地做到这一点,或者你可以把时间花在重新发明轮子上。

于 2012-11-16T09:38:21.090 回答
1

基本上你有一批三个 SQL 语句——一个选择和两个插入。数据库引擎可以在它们之间的任何位置从不同会话执行另一条语句,从而破坏您的数据一致性 - 其他一些会话可以获得与您获得的相同的 MAX() 值并将其用于其他插入语句。阻止数据库引擎这样做的唯一方法是使用事务。用 BEGIN TRANSACTION ... COMMIT 包装你的批次,你就完成了。

于 2012-11-16T07:12:24.527 回答
1

你这样做的方式很好,你需要的是事务处理..

BEGIN TRANSACTION 

begin try
    NextID = Select Max(ID) + 1 From Table

    INSERT INTO Table1(ID, Col1, Col2...) Values(NextId, Value1, Value2...)

    INSERT INTO Table2 (ID,col1,col2....) Values (NextID, Value1, Value2...)

    COMMIT TRANSACTION 
end try

begin catch

    ROLLBACK TRANSACTION 
    --exception logging goes here

end catch
于 2012-11-16T07:35:38.703 回答