以文本方式查看主题

-  Foxtable(狐表)  (http://foxtable.net/bbs/index.asp)
--  专家坐堂  (http://foxtable.net/bbs/list.asp?boardid=2)
----  游标循环出错时如何跳到下一个值继续执行?  (http://foxtable.net/bbs/dispbbs.asp?boardid=2&id=125473)

--  作者:happyft
--  发布时间:2018/9/28 20:37:00
--  游标循环出错时如何跳到下一个值继续执行?
在sql的数据表字段修改后有的视图可能会出错,所以用游标遍历所有视图检查,
...
DECLARE @name VARCHAR(40);
    OPEN MyCursor;
    FETCH NEXT FROM MyCursor
    INTO @name;
    WHILE ( @@fetch_status <> -1 )

        BEGIN

         IF ( @@fetch_status <> -2 )

                BEGIN

                    BEGIN TRY

                       EX EC sp_refreshview @name;

                    END TRY

                    BEGIN CATCH

                        SET @names = @names + \',\' + @name --记录出错的视图

                       如何转到下面的绿色语句进入下一个值循环

                    END CATCH;

                END;

 

            FETCH NE XT FROM MyCursor

        INTO @name;

        END;

    CLOSE MyCursor;

    DEALLOCATE MyCursor;

    PRINT @names;



此主题相关图片如下:tim截图20180928202552.jpg
按此在新窗口浏览图片

目的就是想实现 ,当检查一个视图出错时,将此视图名@name记下,再循环检查下一个视图,直到全部检查完成打印出所有出错的视图.
上面的代码执行出错时就停止了,应该如何才能实现?
谢谢!


--  作者:有点蓝
--  发布时间:2018/9/28 21:04:00
--  
下面代码单独放到一个存储过程中,调用
BEGIN
BEGIN TRY
   EX EC sp_refreshview @name;
END TRY
BEGIN CATCH
SET @names = @names + \',\' + @name --记录出错的视图
   如何转到下面的绿色语句进入下一个值循环
END CATCH;
END;

--  作者:HappyFt
--  发布时间:2018/9/29 10:40:00
--  
主储存过程如下:
ALTER PROCEDURE [dbo].[usp_RefreshAllView]
    @name2 VARCHAR(40) OUTPUT
AS
    DECLARE @names NVARCHAR(MAX);
    DECLARE @name VARCHAR(40);
    DECLARE MyCursor CURSOR
    FOR
        SE LECT  name
        FROM    dbo.sysobjects
        WHERE   OBJECTPROPERTY(id, N\'IsView\') = 1
                AND ( NOT name IN ( \'sysconstraints\', \'syssegments\' )
                    );
    OPEN MyCursor;
    FETCH NEXT FROM MyCursor
    INTO @name;
    WHILE ( @@fetch_status <> -1 )
        BEGIN
            IF ( @@fetch_status <> -2 )
                BEGIN
                    EX EC usp_RefreshAllViewchk @name, @name2 OUTPUT --接收出错返回的值
                    SE T @names = @names + \',\' + @name2; --集合出错的视图
                END;
            FETCH NE XT FROM MyCursor
        INTO @name;
        END;
    CLOSE MyCursor;
    DEALLOCATE MyCursor;
    PRINT @names;

调用的子储存过程如下
ALTER PROCEDURE [dbo].[usp_RefreshAllViewchk]
    (
      @name VARCHAR(40) ,
      @name2 VARCHAR(40) OUTPUT
    )
AS
    BEGIN
        BEGIN TRY
            EX EC sp_refreshview @name;
        END TRY
        BEGIN CATCH
            SE T @name2 = @name;
            RETURN @name2;
        END CATCH;
    END;

运行主储存过程,当出现第一个有错的视图时出错,
消息 245,级别 16,状态 1,过程 usp_RefreshAllViewchk,第 14 行
在将 varchar 值 \'uv_sc002\' 转换成数据类型 int 时失败。
哪里 的问题?
谢谢!


--  作者:有点蓝
--  发布时间:2018/9/29 10:58:00
--  
RETURN @name2;去掉
--  作者:HappyFt
--  发布时间:2018/9/29 11:12:00
--  
去掉执行变成这样了:
消息 266,级别 16,状态 2,过程 usp_RefreshAllViewchk,第 0 行
EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 0,当前计数 = 1。

--  作者:有点蓝
--  发布时间:2018/9/29 11:28:00
--  
RETURN @name2;

改为

RETURN 0;

或者试试

ALTER PROCEDURE [dbo].[usp_RefreshAllViewchk]
    (
      @name VARCHAR(40) ,
      @name2 VARCHAR(40) OUTPUT
    )
AS
    BEGIN
set nocount on
        BEGIN TRY
            EX EC sp_refreshview @name;
        END TRY
        BEGIN CATCH
            SE T @name2 = @name;
        END CATCH;
set nocount off
    END;

--  作者:HappyFt
--  发布时间:2018/9/29 11:37:00
--  
还是不行,两种方式 结果都一样
消息 266,级别 16,状态 2,过程 usp_RefreshAllViewchk,第 0 行
EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 0,当前计数 = 1。
消息 266,级别 16,状态 2,过程 usp_RefreshAllView,第 0 行
EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 0,当前计数 = 1。

(1 行受影响)

(1 行受影响)
消息 3998,级别 16,状态 1,第 1 行
在批处理结束时检测到不可提交的事务。该事务将回滚。


--  作者:有点蓝
--  发布时间:2018/9/29 12:30:00
--  
测试了一下TRYCATCH不会影响游标的处理,出错后会继续处理下一个,不能打印出出错视图的原因是没有初始化@names


ALTER PROCEDURE [dbo].[usp_RefreshAllView]
    @name2 VARCHAR(MAX) OUTPUT
AS
begin
    DECLARE @names NVARCHAR(MAX);
    DECLARE @name VARCHAR(40);
SET @names = \'\';
    DECLARE MyCursor CURSOR
    FOR
        SELECT  name
        FROM    dbo.sysobjects
        WHERE   OBJECTPROPERTY(id, N\'IsView\') = 1
                AND ( NOT name IN ( \'sysconstraints\', \'syssegments\' )
                    );
    OPEN MyCursor;
    FETCH NEXT FROM MyCursor
    INTO @name;
    WHILE ( @@fetch_status <> -1 )
        BEGIN
            IF ( @@fetch_status <> -2 )
                BEGIN
                   BEGIN TRY
                       EXEC sp_refreshview @name;
                    END TRY
                    BEGIN CATCH
                        SET @names = @names + \',\' + @name --记录出错的视图
                    END CATCH;
                END;
            FETCH NEXT FROM MyCursor
        INTO @name;
        END;
    CLOSE MyCursor;
    DEALLOCATE MyCursor;
    PRINT @names;

end
[此贴子已经被作者于2018/9/29 12:31:41编辑过]

--  作者:HappyFt
--  发布时间:2018/9/29 14:30:00
--  
还是有问题:


图片点击可在新窗口打开查看此主题相关图片如下:tim截图20180928202552.jpg
图片点击可在新窗口打开查看

当出现第一个出错的视图后,后面的每一个游标值(视图)都按出错的来处理了,实际后面打印出来的很多视图都是正确的,也就是出错一次就没有再执行begin tray而是统统都按begin catch来执行了.

--  作者:有点蓝
--  发布时间:2018/9/29 15:13:00
--  
我测试正常,有问题的才会记录。至于上面的错误应该不是这里引起的

BEGIN TRY
EXEC sp_refreshview @name;
SET @names = @names + \',ok=\' + @name --记录正确的视图
END TRY
BEGIN CATCH
SET @names = @names + \',*********\' + @name --记录出错的视图
END CATCH;

我的测试结果是
,ok=vGetSubList,ok=vChoiceQuestionDetail,ok=vJudgmentQuestionDetail,ok=vCodingQuestionDetail,ok=vAnswerList,*********vUsersTestGroup,*********vGetUsersQuestionCount,ok=vAllSubjectCount,ok=vQuestionAmount,ok=vGetQuestionTypeLevelCount,ok=vCheckUpdateTime,*********vGetUserLastAnswerDate,ok=vIgnoreQuestions,ok=vConsecutiveError5Times,*********vGetAnswerQuestionCount,*********vGetUserErrorQuestions