SQL命令的正确隔离级别

SQL命令的正确隔离级别,sql,sql-server,database,transactions,ado.net,Sql,Sql Server,Database,Transactions,Ado.net,我想运行这个SQL语句,将一个新的列组插入到列组表中。主键rank\u id是一个字符字段,因此它不会自动递增。因此,我使用TOP关键字获取最后一个ID,然后在SQL中递增它 const string InsertStatement = @"BEGIN DECLARE @ID INT = (SELECT TOP 1 (rank_id + 1) FROM Rank ORDER BY [rank].rank_id DESC) INSER

我想运行这个SQL语句,将一个新的列组插入到列组表中。主键
rank\u id
是一个字符字段,因此它不会自动递增。因此,我使用
TOP
关键字获取最后一个ID,然后在SQL中递增它

const string InsertStatement = @"BEGIN DECLARE @ID INT = (SELECT TOP 1 (rank_id + 1) FROM Rank ORDER BY [rank].rank_id DESC) 
                               INSERT INTO RANK (rank_id, rank_name, shift_rate, revised_date) VALUES (@ID, @rank, @rate, @date) END"
我认为我应该处理这个事务以避免脏读,否则其他用户可能会读取错误的ID作为最后一个ID。我说得对吗?那么,对于这种情况,正确的隔离级别是什么?这个呢

using(var Trans = sqlConnection.BeginTransaction(IsolationLevel.Serializable))

您可以从SQL端解决这个问题。以下方法可以实现此目的:

INSERT RANK (rank_id, rank_name, shift_rate, revised_date)
 select max(rank_id) + 1, @rank, @rate, @date
  from RANK
它是一条语句,因此是一个原子事务——也就是说,它在表上获得自己的锁(如果有索引的话,还有索引),确保没有其他同时运行的完全相同的查询能够“获取”下一个值

脏读几乎是不可能的,因为它都是在一条语句中完成的(可能是非常快的)。这使您获得了原子性——单个语句总是绑定在它们自己的“隐式事务”中。在列上添加一个主键约束,就应该这样做了


我觉得有义务提到,如果你的字符列中有非数字值,你会遇到问题…

为什么不干脆
IsolationLevel.ReadCommitted
@Rahul我想这就是他要问的。。。他真的需要使用像
Serializable
这样残酷的东西,还是可以用限制性更小的东西(比如
ReadCommitted
)来逃避惩罚<代码>数据可以通过当前事务中单个语句之间的其他事务进行更改…可以更改的
是什么意思?
?如果您愿意升级到SQL 2012 Express,可以使用。这应该可以让你完全避免这个问题。像这样的“滚动你自己的”递增数字充满了问题。并发性是这类事情的一个主要问题。如果你想坚持这一点,我建议使用MAX(rank_id)+1,而不是带有order by的TOP 1。