Sql server 在并发环境中处理max(ID)

Sql server 在并发环境中处理max(ID),sql-server,sql-server-2005,Sql Server,Sql Server 2005,我不熟悉使用关系数据库管理系统(如SQL Server)进行web应用程序编程和处理并发性。我使用的是SQLServer2005Express版 我正在生成员工代码,其中最后四位数字来自此查询: SELECT max(ID) FROM employees WHERE district = "XYZ"; 我不了解如何处理由于并发连接而可能出现的问题。许多用户可以选择相同的max(ID),当一个用户单击“保存记录”时,该ID可能已被另一个用户占用 如何处理这个问题?这可以通过以下方式完成。例如,如

我不熟悉使用关系数据库管理系统(如SQL Server)进行web应用程序编程和处理并发性。我使用的是SQLServer2005Express版

我正在生成员工代码,其中最后四位数字来自此查询:

SELECT max(ID) FROM employees WHERE district = "XYZ";
我不了解如何处理由于并发连接而可能出现的问题。许多用户可以选择相同的max(ID),当一个用户单击“保存记录”时,该ID可能已被另一个用户占用

如何处理这个问题?

这可以通过以下方式完成。例如,如果您指定SERIALIZABLE作为级别,那么其他事务将被阻止,这样您就不会遇到此问题


如果我没有正确理解你的问题,请告诉我。

这里有两种方法可以满足你的要求。您可能会在
EmpCode
上遇到唯一的约束冲突,这一事实让您担心:)

1。用于获取最后插入的ID,并使用该ID计算
EmpCode

表定义:

create table Employees
(
  ID int identity primary key,
  Created datetime not null default getdate(),
  DistrictCode char(2) not null,
  EmpCode char(10) not null default left(newid(), 10) unique
)
create table Employees
(
  ID int identity primary key,
  Created datetime not null default getdate(),
  DistrictCode char(2) not null,
  EmpCode as cast(year(Created) as char(4))+DistrictCode+right(10000+ID, 4) unique
)
向员工添加一行。应在事务中执行,以确保不会留下
EmpCode
left(newid(),10)
中的默认随机值:

declare @ID int

insert into Employees (DistrictCode) values ('AB')

set @ID = scope_identity()

update Employees
set EmpCode = cast(year(Created) as char(4))+DistrictCode+right(10000+@ID, 4)
where ID = @ID 
2.Make
EmpCode
a

表定义:

create table Employees
(
  ID int identity primary key,
  Created datetime not null default getdate(),
  DistrictCode char(2) not null,
  EmpCode char(10) not null default left(newid(), 10) unique
)
create table Employees
(
  ID int identity primary key,
  Created datetime not null default getdate(),
  DistrictCode char(2) not null,
  EmpCode as cast(year(Created) as char(4))+DistrictCode+right(10000+ID, 4) unique
)
向员工添加一行:

insert into Employees (DistrictCode) values ('AB')

使用MAX是个坏主意,因为有了适当的锁定机制,您将无法在同一个区域的多个线程中插入行。 如果一次只能创建一个用户对您来说是可以的,并且如果您的测试显示,即使每个地区有很多用户,最大值也会增大,那么使用它可能是可以的。 长话短说,处理同一性,尽可能多地依赖同一性。真的

但如果不可能,一种解决方案是在单独的表中处理ID

Create Table DistrictID (
    DistrictCode char(2),
    LastID Int,
    Constraint PK_DistrictCode Primary Key Clustered (DistrictCode)
);
然后递增LastID计数器。如果您想在并行线程中创建多个用户,那么增加ID是一个与用户创建事务分离的事务,这一点很重要。您可以限制仅按顺序生成ID

代码可以如下所示:

Create Procedure usp_GetNewId(@DistrictCode char(2), @NewId Int Output)
As

Set NoCount On;
Set Transaction Isolation Level Repeatable Read;
Begin Tran;
Select @NewId = LastID From DistrictID With (XLock) Where DistrictCode = @DistrictCode;
Update DistrictID Set LastID = LastID + 1 Where DistrictCode = @DistrictCode;
Commit Tran;
可重复读取XLOCK关键字是避免两个线程获得相同ID所需的最小值。
如果表中没有所有区域,则需要将可重复读取更改为可序列化,并在使用自动增量列时,使用插入来叉入更新,或者使查询具有事务性,以便一次只执行一个查询。是否获取给定地区的最大ID?你怎么处理那个身份证?ID列是标识列吗?什么时候执行查询?就在插入之后,您想将新创建的ID用于某个对象?该ID与其他对象组合,形成一个十位数字代码。当用户单击“保存”按钮时,会调用GenerateID()函数。能否显示GenerateID()的代码?也许有其他方法可以做到这一点。ID是自动递增的标识列吗?是,它是自动递增的列。GenerateId()函数中没有什么特殊的内容。选择当年的4位数字,2位区号,4位保留为max(ID)。这使其成为一个10位数的员工代码。