Ответ здесь зависит от размера / проблем параллелизма в вашей системе.Если вы НЕ УВЕРЕНЫ в отношении проблем параллелизма, предположите, что доступ является многопоточным.
Однопоточный
Если у вас небольшая система или вы можете быть уверены, что только один поток будет касаться этой функции одновременно, тогда будет работать что-то вроде следующего:
CREATE PROCEDURE some_proc ( @KeyPart1 smallint, @newSeq smallint OUTPUT )
AS
DECLARE @KeyPart1 int
DECLARE @KeyPart2 int
SET @KeyPart1 = (SELECT <whatever your logic is here>)
SET @KeyPart2 = select max(order_seq) + 1 from mytable where some_id = @KeyPart1
insert into mytable (some_id, order_seq)
values ( @KeyPart1, @KeyPart2 )
set @newSeq = @KeyPart2
Многопоточный доступ
Если вы не можете быть уверены , что толькоодин поток будет обращаться к процессу, затем вам понадобится транзакция в вашем коде.Из того, что вы поделились, кажется, что вам понадобится транзакция SERIALIZABLE
.SERIALIZABLE
- это наименее одновременная (и наиболее защищенная) транзакция, доступная в SQL Server.Поскольку вы выполняете чтение, идентифицирующее max
, вам потребуется сериализация, чтобы предотвратить фантомные вставки, которые могут изменить результат.
Хотя вы, вероятно, захотите обработать ошибки, процедура, подобная следующей, должна работать ....
CREATE PROCEDURE some_proc ( @KeyPart1 smallint, @newSeq smallint OUTPUT )
AS
DECLARE @KeyPart1 int
DECLARE @KeyPart2 int
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN
SET @KeyPart1 = (SELECT <whatever your logic is here>)
SET @KeyPart2 = select max(order_seq) + 1 from mytable where some_id = @KeyPart1
insert into mytable (some_id, order_seq)
values ( @KeyPart1, @KeyPart2 )
set @newSeq = @KeyPart2
COMMIT TRAN