Это хранимая процедура по любой причине, эта циклическая перма
Я должен сделать несколько ударов
, когда я впервые использую SCROLL KEYSET SCROLL_LOCKS
и WHERE CURRENT OF
краткое объяснение того, что это делает: замена временного идентификатора для многих строк постоянным идентификатором, который является MAX(num_subproceso)+1
, но я хочу, чтобы это делалось в ACID-режиме для устранения возможных совпадений.
IЯ не могу использовать транзакцию непосредственно в моем приложении, причина в том, что я использую набор классов моего авторства, которые абстрагируют структуру базы данных и поведение данных таким образом, только недостатком моей конкретной реализации являетсячто я не могу использовать транзакцию, потому что мой код часто в циклах быстрого открытия / закрытия соединения, и мне нужно сделать транзакцию из большого количества sqls.
Чтобы избежать этого, я закончил генерировать отрицательный случайный идентификатор для записи строк в базу данных, а затем использовал сохраненный процесс для использования транзакции и использования курсора с блокировкой строки, чтобы избежать (может быть, я ошибаюсь здесь)этот другой пользователь получает тот же идентификатор, используя MAX (...) + 1, и возникает проблема, когда 2 пользователя пишут один и тот же первичный ключ.
Почему я говорю, что предотвращаю проблему параллелизма (я могошибаться): если я блокирую строку, которую я использую, а другой пользователь выполняет операцию (например, MAX (...), чтобы получить новый идентификатор) над всем набором строк в той же таблице, блокировка, котораяблокирование моей строки предотвращает получение 2-м клиентом результата и остается в состоянии ожидания до тех пор, пока не будет снята моя блокировка
Процесс длинный и выполняет различные шаги таким образом, чтобы проходить время между началом и завершением всего процесса.
... постоянный идентификатор - это максимальное число идентификаторов этого типа плюс один ... таким образом;в то время как временный идентификатор вначале одинаков, постоянный идентификатор может варьироваться
пример данных
(до)
cve_subproceso (PK) | num_subproceso (PK) | inidate (dd-mm-yyyy hh:MM:ss)
--------------------+---------------------+---------------------
A01 | -27813578125 | 01-05-2011 09:00:00
A02 | -27813578125 | 15-05-2011 10:00:00
A03 | -27813578125 | 16-05-2011 07:30:00
A07 | -27813578125 | 21-05-2011 09:15:00
A12 | -27813578125 | 30-05-2011 10:00:00
... | ... | ...
(после)
cve_subproceso (PK) | num_subproceso (PK) | inidate (dd-mm-yyyy hh:MM:ss)
--------------------+---------------------+---------------------
A01 | 157 | 01-05-2011 09:00:00
A02 | 122 | 15-05-2011 10:00:00
A03 | 15 | 16-05-2011 07:30:00
A07 | 90 | 21-05-2011 09:15:00
A12 | 140 | 30-05-2011 10:00:00
... | ... | ...
Как рассчитывается [num_subproceso]
номер постоянного идентификатора основан на количестве [cve_subproceso] в таблице.
, относящихся к этому примеру ... существует или существовало взаданное время 156 'A01' изменяется от 1 до 156, когда я добавляю 157 к A01 в этом случае, потому что я вычислил MAX ([num_subproceso]) и MAX () возвратил 156
cve_subproceso (PK) | num_subproceso (PK) | inidate (dd-mm-yyyy hh:MM:ss)
--------------------+---------------------+---------------------
A01 | 156 | 01-05-2011 09:00:00
A01 | 155 | 15-04-2011 10:00:00
A01 | 154 | 03-04-2011 07:30:00
A01 | 152 | 11-03-2011 09:15:00
A01 | 151 | 10-01-2011 10:00:00
... | ... | ...
я повторяюта же операция для каждого значения [cve_subproceso] ...
SP-код
ALTER PROCEDURE [dbo].[ReprocesarEventos]
-- Add the parameters for the stored procedure here
@numSubproceso int = 0
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
BEGIN TRANSACTION;
-- Insert statements for procedure here
DECLARE @nuevoID integer;
DECLARE @cveSubProc varchar(4);
DECLARE cUpd CURSOR SCROLL KEYSET SCROLL_LOCKS
FOR SELECT [cve_subproceso] FROM [dbo].[calendario] WHERE [num_subproceso]= @numSubproceso
FOR UPDATE OF [num_subproceso];
OPEN cUpd;
FETCH NEXT FROM cUpd INTO @cveSubProc;
WHILE (@@FETCH_STATUS <> -1)
BEGIN
IF (@@FETCH_STATUS <> -2)
BEGIN
SELECT @nuevoID=(ISNULL(MAX([num_subproceso]),0)+1) FROM [dbo].[calendario] WHERE [cve_subproceso]=RTRIM(LTRIM(@cveSubProc));
IF(@nuevoID < 0)
BEGIN
SET @nuevoID = 1;
END;
UPDATE [dbo].[calendario] SET [num_subproceso]=@nuevoID WHERE CURRENT OF cUpd;
END;
FETCH NEXT FROM cUpd INTO @cveSubProc;
END;
CLOSE cUpd;
DEALLOCATE cUpd;
IF(@@ERROR <> 0)
BEGIN
-- Rollback the transaction
ROLLBACK TRANSACTION;
-- Raise an error and return
RAISERROR ('Oops! - something went wrong.', 16, 1);
RETURN;
END;
COMMIT TRANSACTION;
END;
что здесь не так?