По определению СИНГЛЕТОН - БЛОКИРОВКА.
Говоря о базах данных, есть так много профессионалов БД, которые боятся, когда вы упоминаете слово «блокировка», но блокировки как таковые не являются проблемой, они являются фундаментальным механизмом для реляционных баз данных.
Вы должны узнать, как работают замки, какие замки существуют и относиться к ним с уважением. Всегда работайте с короткими транзакциями, блокируйте минимальные строки, как можете, работайте с наборами не отдельных строк. Замки становятся проблемой, когда они массивны, и когда они слишком много, и, конечно, когда вы создаете DEADLOCK.
Итак, золотое правило, когда вы должны изменить данные в транзакцию, сначала установите эксклюзивную блокировку (UPDATE), а не общую блокировку (SELECT), это означает, что иногда вам нужно начинать делать ложный LOCK, как в:
BEGIN TRAN
UPDATE table
set col1 = col1
Where Key = @Key
.......
COMMIT TRAN
до SQL Server 2012, когда мне нужен серийный я сделал это двумя способами:
создать столбец IDENTITY, поэтому после установки вы можете получить значение с помощью встроенной функции SCOPE_IDENTITY() есть также @@ IDENTITY, но если кто-то создает триггер, который вставляет в другую таблицу с столбец идентичности запускает кошмар.
CREATE TABLE [table]
(
Id int IDENTITY(1,1) NOT NULL,
col2 ....
col3 ....
)
Второй вариант заключается в добавлении последовательного столбца обычно в родительской таблице или таблице сделали для него плюс процедуры (вы можете использовать код клиента), чтобы получить серийный номер:
--IF YOU CREATE A SERIAL HERE YOU'LL SPENT SOME SPACE,
--BUT IT WILL KEEP YOUR BLOCKINGS VERY LOW
CREATE TABLE Parent
(
Id,
ChildSerial int not null,
col2 ...
col3 ...
CONSTRAINT PK_Parent PRIMARY KEY (Id)
)
GO
--NAMED CONSTRAINT Auto names are random (avoid them)
ALTER TABLE Parent
ADD CONSTRAINT Parent_DF_ChildSerial DEFAULT(0) FOR ChildSerial;
GO
CREATE TABLE Child
(
Id int not null
col2..
colN..
--PLUS PRIMARY KEY... INDEXES, etc.
)
CREATE PROC GetChildId
(
@PatentId int
@ChildSerial int output --To use the proc from another proc
)
As
Begin
BEGIN TRAN
--YOU START WITH A LOCK, SO YOU'LL NEVER GET A DEADLOCK
--NOR A FAKE SERIAL (Two clients with the same number)
UPDATE Parent
SET ChildSerial = ChildSerial + 1
WHERE Id = @PatentId
If @@error != 0
Begin
SELECT @ChildSerial = -1
SELECT @ChildSerial
ROLLBACK TRAN
RETURN
End
SELECT @ChildSerial = ChildSerial
FROM Parent
WHERE Id = @PatentId
COMMIT TRAN
SELECT @ChildSerial --To Use the proc easily from a program
End
Go
Может вам не использовать последовательность? –
Если вы правильно поняли, вы можете использовать что-то вроде этого: «update T set ID + = 1 output inserted.ID» –
Или, если это было предыдущее значение, которое вы хотели, тогда 'update T set ID + = 1 output deleted.ID' –