1

У меня есть база данных SQL Server 2005. Table A имеет в нем столбец идентичности, а также другой столбец Id, который охватывает несколько строк. Второй столбец id находится в формате '0000000098' и должен быть строкой. Я не могу изменить тип данных.Функция SQL Server - предотвратить дубликаты

Function A получает значение max ID, увеличивает его на единицу, отливая как строку.

Мой сохраненный proc получает новый идентификатор, а затем делает несколько вложений, используя этот идентификатор.

Как я могу запретить двум клиентам выполнять хранимую процедуру и получать одинаковые идентификаторы до того, как произойдет обновление? Могу ли я заблокировать таблицу a от чтения до тех пор, пока proc не будет обработан или не будет более эффективным способом?

Если бы я мог изменить тип данных и/или структуру, это было бы легко, но я не могу.

ответ

1

Если вы можете сформулировать ваша функция как один оператор UPDATE, то явная блокировка не требуется - для оператора UPDATE потребуется блокировка обновления (U), и это является эксклюзивным, например ни один из двух читателей не может получить блокировку обновления в одной строке одновременно.

UPDATE dbo.TableA 
SET ManualID = CAST(CAST(ManualID AS INT) + 1 AS VARCHAR(20)) 
OUTPUT Inserted.ManualID -- return the newly inserted manual ID for your use 
WHERE .......... 

Если вам нужно иметь два шага процесса - SELECT перед тем UPDATE - то я бы использовать WITH (UPDLOCK) намек на SELECT

DECLARE @OldManualID VARCHAR(20) 

BEGIN TRANSACTION 

SELECT @OldManualID = ManualID 
FROM dbo.TableA WITH (UPDLOCK) 
WHERE........ 

-- do something with that manual ID 

UPDATE dbo.TableA 
SET ManualID = (new value of ManualID) 
WHERE .......... 

COMMIT TRANSACTION 

В обоих случаях, так как одного UPDATE или SELECT/UDPATE выполняется под блокировкой обновлений, одновременно два процесса могут запускать это. Я не думаю, что вам нужна дальнейшая блокировка вообще - определенно не общий столовый замок.

+0

Это хорошая идея. Интересно, если два человека запускали скрипт в одно и то же время, если это возможно 1) Запустите функцию и получите следующий идентификатор 2) Следующий человек получит следующий идентификатор 3) Первый человек запускает инструкцию вставки ПОСЛЕ того, как второй человек получает следующий идентификатор ... В результате оба имеют одинаковый идентификатор. Возможно ли это, или потому, что он делает вставку, автоматически ли она блокирует эту таблицу? Это для учетных таблиц, поэтому я не могу позволить себе дублировать идентификаторы ... Учет ночных кошмаров хуже любого другого рода! ;) –

+1

Nevermind, я просто перечитываю ваше сообщение ... Имеет смысл, спасибо! (Дети вокруг - не могут сосредоточиться) –

0

Да, вы можете заблокировать стол. Вам необходимо сделать все, что находится внутри транзакции, и когда вы впервые прочитаете таблицу, вы можете разместить на ней эксклюзивный непрерывный замок с подсказками (updlock, holdlock) или даже (TABLOCKX)

Смежные вопросы