Использование MAX - плохая идея, поскольку при правильном механизме блокировки вы не сможете вставлять строки в несколько потоков для одного района.Если для вас нормально, что вы можете создавать только одного пользователя за раз, и если ваши тесты показывают, что MAX расширяется даже при большом количестве пользователей в каждом районе, возможно, будет правильным его использовать.Короче говоря, имея дело с идентичностями, насколько это возможно, вы должны полагаться на IDENTITY.Действительно.
Но если это невозможно, одним из решений является обработка идентификаторов в отдельной таблице.
Create Table DistrictID (
DistrictCode char(2),
LastID Int,
Constraint PK_DistrictCode Primary Key Clustered (DistrictCode)
);
Затем вы увеличиваете счетчик LastID.Важно, чтобы инкрементные идентификаторы были транзакцией, отделенной от транзакции создания пользователя, если вы хотите создать много пользователей в параллельных потоках.Вы можете ограничить генерацию идентификатора в последовательности.
Код может выглядеть следующим образом:
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 ключевые слова - это минимум, который вам нужен, чтобы избежать двух потоков, чтобы получить одинаковый идентификатор.Если в таблице не все районы, вам нужно изменить Повторяемое чтение на Сериализуемый и раскошелиться на Обновление с Вставить .