我已经看到了很多与我的问题有关的外围信息,但没有直接关键。我有一些代码可以刷新视图,但有时视图已经变得无效,因为某个地方已经破坏了依赖关系或其他什么。我需要删除任何此类无效视图。我的代码的主要部分工作正常,看起来像这样(所有变量和游标定义留待空间考虑):
BEGIN TRY
BEGIN TRANSACTION T1
EXEC sp_refreshview @view
PRINT @view
COMMIT TRANSACTION T1
END TRY
BEGIN CATCH -- If the view can't be refreshed, it's because it's invalid. Delete it.
PRINT 'deleting invalid view: recorded error in this refreshView on : ' + @view
ROLLBACK TRANSACTION T1
SET @drop_view_command = N'DROP VIEW ' + @view;
EXEC sys.sp_executesql @stmt = @drop_view_command
END CATCH;
当然,这段代码在带有游标的while循环中,并且所有变量都在顶部正确定义。到现在为止还挺好。但是,我需要使用它自己的事务从更大的脚本中运行此代码。因此,我将此代码包含在其自己的sp_executesql
调用中。
IF (@errval = 0)
BEGIN
EXEC @errval = sys.sp_executesql @stmt = N'
--previous code in here, with quotes correctly escaped
'
END
当我这样做时,它失败了
无法回滚T1。没有找到该名称的交易或保存点。
我不是专家级DB开发人员;有没有关于嵌套交易的东西,我没有到这里?为什么代码可以正常运行,但不在sp_executesql
调用内?
我正在运行SQL Server 2008。
哦,我也很幸运能够在停机期间运行这个脚本,因此在运行时我不需要担心任何其他用户。
已编辑经过大量研究后,似乎这个问题与SQL服务器中并不真正支持嵌套事务有关。 catch块中的我的ROLLBACK将使用它自己的事务回滚整个调用脚本,这根本不是我想做的事情。我想删除导致问题的视图,并在我的路上继续愉快。这就是代码单独工作的原因,但是在从另一个调用sp_executesql的事务中调用时却没有。
我试图找到一种方法以某种方式捕获sp_refreshview上的错误,但显然它设置了XACT_STATE = -1,这意味着我只是注定了。
任何聪明的想法?
答案 0 :(得分:0)
事实证明,由于sp_refreshview是一个事务杀手,嵌套事务并没有按预期工作,答案是将sp_refreshview调用更改为会引发捕获错误的事情。我在这里为其他可能遇到此问题的人提供此解决方案。
此代码成功运行,无论是自己运行,还是从sp_executesql调用的较大事务中运行。
BEGIN TRY
SET @statement = 'SELECT * INTO #view_temp FROM + ' @view + ' WHERE 1 = 2'
EXEC @exec_err = sp_executesql @stmt = @statement
PRINT 'Refreshing view ' + @view
EXEC sp_refreshview @view
END TRY
BEGIN CATCH
PRINT 'deleting invalid view: recorded error in this refreshView on : ' + @view
SET @drop_view_command = N'DROP VIEW ' + @view;
EXEC sys.sp_executesql @stmt = @drop_view_command
END CATCH