内部sp_executesql

时间:2016-08-10 20:46:37

标签: sql-server-2008 tsql

我已经看到了很多与我的问题有关的外围信息,但没有直接关键。我有一些代码可以刷新视图,但有时视图已经变得无效,因为某个地方已经破坏了依赖关系或其他什么。我需要删除任何此类无效视图。我的代码的主要部分工作正常,看起来像这样(所有变量和游标定义留待空间考虑):

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,这意味着我只是注定了。

任何聪明的想法?

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