Ниже приведен код, который я запускаю (готов для копирования и вставки на SQL сервер). По сути, я пытаюсь использовать WHILE L OOP для вставки записей из одной таблицы в новую таблицу один за другим и записывать результаты каждой вставки, используя третью таблицу. Как только я смогу решить эту проблему, этот код будет настроен и использован в нескольких хранимых процедурах.
Вот код:
SET NOCOUNT ON;
BEGIN TRY
BEGIN TRANSACTION
--Create dummy tables
DROP TABLE IF EXISTS #OldTable
DROP TABLE IF EXISTS #NewTable
DROP TABLE IF EXISTS #LoggingTable
CREATE TABLE #OldTable (
ID int IDENTITY(1,1) NOT NULL PRIMARY KEY
,OldValue varchar(64)
)
INSERT INTO #OldTable
VALUES
('1')
,('2')
,('3')
,('Four')
,('Five')
,('6')
,('Seven')
CREATE TABLE #NewTable (
ID int IDENTITY(1,1) NOT NULL PRIMARY KEY
,NewValue int
)
CREATE TABLE #LoggingTable (
ID int IDENTITY(1,1) NOT NULL PRIMARY KEY
,OldTableID int NULL
,NewTableID int NULL
,InsertStatus varchar(MAX)
)
--Begin insert loop
DECLARE @currentID int = NULL
DECLARE THIS_CURSOR CURSOR FAST_FORWARD FOR
SELECT ID FROM #OldTable ORDER BY ID
OPEN THIS_CURSOR
FETCH NEXT FROM THIS_CURSOR INTO @currentID
WHILE @@FETCH_STATUS = 0
BEGIN
BEGIN TRY
--Perform insert
INSERT INTO #NewTable
OUTPUT @currentID, INSERTED.ID, 'Insert successful' INTO #LoggingTable (OldTableID, NewTableID, InsertStatus)
SELECT CAST(OldValue AS int) FROM #OldTable WHERE ID = @currentID
FETCH NEXT FROM THIS_CURSOR INTO @currentID
END TRY
BEGIN CATCH
INSERT INTO #LoggingTable (OldTableID, NewTableID, InsertStatus) VALUES (@currentID, NULL, 'Error occurred during insert operation')
FETCH NEXT FROM THIS_CURSOR INTO @currentID
END CATCH
END
CLOSE THIS_CURSOR
DEALLOCATE THIS_CURSOR
SELECT * FROM #OldTable
SELECT * FROM #NewTable
SELECT * FROM #LoggingTable
COMMIT TRANSACTION
END TRY
BEGIN CATCH
PRINT 'An error has occurred';
-- Test if the transaction is uncommittable.
IF XACT_STATE() = -1
BEGIN
PRINT 'The transaction is in an uncommittable state. Rolling back transaction.';
ROLLBACK TRANSACTION;
END;
-- Test if the transaction is committable.
IF XACT_STATE() = 1
BEGIN
PRINT 'The transaction is committable. Committing transaction.';
COMMIT TRANSACTION;
END;
THROW;
END CATCH
Вот сообщение об ошибке, которое я получаю:
Текущая транзакция не может быть зафиксирована и не может поддерживать операции записи в файл журнала. Откатите транзакцию.
Эта строка выглядит так:
INSERT INTO #LoggingTable (OldTableID, NewTableID, InsertStatus) VALUES (@currentID, NULL, 'Error occurred during insert operation')
Однако, если я закомментирую эту строку (которая мне все еще нужна!), Она просто переместится на другая строка в коде, что обычно означает, что происходит что-то еще. Я уже провел тщательный поиск в Интернете и до сих пор не уверен, в чем причина этой ошибки.
Самая странная часть этой ошибки - если вы удалите внешние TRY CATCH
и TRANSACTION
, скрипт работает точно так, как задумано, без проблем; тем не менее, это не жизнеспособное решение IMHO из-за необходимости надлежащего перехвата ошибок и обработки транзакций, как только оно включено в хранимую процедуру.