我在SQL中有以下光标:
DECLARE @Script varchar(max)
DECLARE @getScript CURSOR
SET @getScript = CURSOR FOR
SELECT [Script]
FROM ScriptTable
OPEN @getScript
FETCH NEXT
FROM @getScript INTO @Script
WHILE @@FETCH_STATUS = 0
BEGIN
BEGIN TRY
EXEC(@Script) --Working part. This executes the query stored in the Script column.
--For example INSERT INTO zTest VALUES(VAL1, VAL2, etc etc..)
UPDATE ScriptTable
SET DateDone = GETDATE(), IsDone = 1, Err = NULL
FETCH NEXT
FROM @getScript INTO @Script
END TRY
BEGIN CATCH
DECLARE @Err varchar(max)
SET @Err = ERROR_MESSAGE()
UPDATE ScriptTable
SET DateDone = GETDATE(), Err = @Err
END CATCH
END
CLOSE @getScript
DEALLOCATE @getScript
Q1: 目前,我在执行EXEC(@Script)时将值插入到注释中指定的“zTest”表中。
但是,“更新ScriptTable”的第二部分更新了我的脚本表中的所有行。我知道我需要为光标移动的相应行指定ID。问题是,我该怎么做?我不想只更新相应的行,移到下一行然后更新那一行。
Q2: 我的下一个问题是,在CATCH块中,我认为一旦ScriptTable的脚本列中的一个查询出现错误,我就会创建一个无限循环,就像我查看结果一样,它只是继续前进和前进。我不想破坏;这个过程因为我想把错误写入Err列并继续下一行直到它到达@Script的末尾,然后停止。
IDENT_CURRENT,Scope_Identity等不起作用,因为我没有在脚本表中插入任何内容。
请帮忙。
答案 0 :(得分:2)
关于Q1,你必须有一个主键才能使用光标进行更新(虽然有解决方法)。
一般来说,你会想要这样的语法:
update ScriptTable
SET DateDone = GETDATE(), IsDone = 1, Err = NULL
where ID of @getScript
关于Q2,它是无限循环的意义。当您使用TRY
和CATCH
子句但它失败时,它不会执行TRY
“区域中的任何语法”。
因此,FETCH NEXT
被跳过,并且在下一个循环中再次发生相同的错误
尽量确保循环中始终有FETCH NEXT
。
希望这会对你有所帮助。
答案 1 :(得分:1)
如果有兴趣的话,这是我的最终代码:
DECLARE @Script varchar(max)
DECLARE @getScript CURSOR
SET @getScript = CURSOR FOR
SELECT [Script]
FROM ScriptControl
OPEN @getScript
FETCH NEXT
FROM @getScript INTO @Script
DECLARE @Counter int = 1
WHILE @@FETCH_STATUS = 0
BEGIN
BEGIN TRY
EXEC(@Script)
UPDATE ScriptControl
SET DateDone = GETDATE(), IsDone = 1, Error = NULL WHERE ID = @Counter
FETCH NEXT
FROM @getScript INTO @Script
SET @Counter = (@Counter + 1)
END TRY
BEGIN CATCH
DECLARE @Err varchar(max)
SET @Err = ERROR_MESSAGE()
UPDATE ScriptControl
SET CSC_EOD_DateDone = NULL, CSC_EOD_Err = @Err, CSC_EOD_IsDone = 0 WHERE CURRENT OF @getScript
FETCH NEXT
FROM @getScript INTO @Script
SET @Counter = (@Counter + 1)
END CATCH
END
CLOSE @getScript
DEALLOCATE @getScript
答案 2 :(得分:1)
此:
DECLARE @ScriptControlId INT, @Script VARCHAR(MAX)
DECLARE @getScript CURSOR
SET @getScript = CURSOR FOR
SELECT [ID], [Script]
FROM ScriptControl
OPEN @getScript
FETCH NEXT
FROM @getScript INTO @ScriptControlId, @Script
WHILE @@FETCH_STATUS = 0
BEGIN
BEGIN TRY
EXEC(@Script)
UPDATE ScriptControl
SET DateDone = GETDATE(), IsDone = 1, Error = NULL
WHERE ID = @ScriptControlId
FETCH NEXT FROM @getScript INTO @ScriptControlId, @Script
END TRY
BEGIN CATCH
DECLARE @Err VARCHAR(MAX) = ERROR_MESSAGE()
UPDATE ScriptControl
SET DateDone = NULL, Error = @Err, IsDone = 0
WHERE CURRENT OF @getScript
FETCH NEXT FROM @getScript INTO @ScriptControlId, @Script
END CATCH
END
CLOSE @getScript
DEALLOCATE @getScript
或者这个:
DECLARE @Script VARCHAR(MAX)
DECLARE @getScript CURSOR
SET @getScript = CURSOR FOR
SELECT [Script]
FROM ScriptControl
OPEN @getScript
FETCH NEXT
FROM @getScript INTO @Script
WHILE @@FETCH_STATUS = 0
BEGIN
BEGIN TRY
EXEC(@Script)
UPDATE ScriptControl
SET DateDone = GETDATE(), IsDone = 1, Error = NULL
WHERE CURRENT OF @getScript
FETCH NEXT FROM @getScript INTO @Script
END TRY
BEGIN CATCH
DECLARE @Err VARCHAR(MAX) = ERROR_MESSAGE()
UPDATE ScriptControl
SET DateDone = NULL, Error = @Err, IsDone = 0
WHERE CURRENT OF @getScript
FETCH NEXT FROM @getScript INTO @Script
END CATCH
END
CLOSE @getScript
DEALLOCATE @getScript