问题一:这里的“SAVE TRANSACTION ”的作用是什么?      是设置一个回滚标记吗???
设置一个事务的保存点,可以用于回滚特定部分问题二:SQL语句成功执行完了,这里并没有用“goto LABCOMMIT”手动提交事务。        SQL语句执行完后,事务会自动提交对吧???
不会用了begin tran,就要显式使用commit/rollback
问题三:在“BEGIN TRANSACTION”外面加一个判断,和在它里面加个判断应该都没有问题吧???  
当然有,在里面加算是事务里面的东西,在外面加就不算这个事务的东西,在回滚时有不同的结果

解决方案 »

  1.   

    用Goto语句,感觉比较好看啊,有错误就跳到回滚。   但有什么特别注意的地方吗???
      

  2.   

    GOTO在C/SQL里面都不建议使用,在很长的代码里面,goto会导致数据流的混乱,调试起来很麻烦
      

  3.   


    谢谢大师,但是,这个模板已经在使用了。  事务好像会自动提交的,数据已经插入和更新到表了。USE [CloudDatasCenter]
    GO
    /****** Object:  StoredProcedure [dbo].[sp_DataComputer_WenYuanDatas]    Script Date: 07/09/2014 15:14:48 ******/
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    ALTER  procedure [dbo].[sp_DataComputer_WenYuanDatas]
    @DANo             Char(32),--20110112182345207插入时间
        @DATime           Datetime,--采集时间
        @LogTime          Datetime,--更新时间
        @MeterType        Char(4),--表具类型
        @MeterNo          Char(20),--表具号码
        @Qty              Decimal(18,6),--数值
        @Unit             Char(4),--单位
        @outputpar int = 0 output--输出返回值
    as--带事务存储过程模板
    begin
    --开始事务
    BEGIN TRANSACTION
    SAVE TRANSACTION sp_Datacomputer_TRANS --事务内容,计算时日月数据.
        
        Declare @DAYear       Char(4);
    Declare @DAMonth      Char(2);
    Declare @DADay        Char(2);
        Declare @DAHour        Char(2); Declare @RowCnt_Year       Int;
    Declare @RowCnt_Month       Int;
    Declare @RowCnt_Day       Int;
    Declare @RowCnt_Hour       Int; Set @DAYear  = Substring(Ltrim(Rtrim(Convert(varchar(10),@DATime,120))),1,4);
    Set @DAMonth = Substring(Ltrim(Rtrim(Convert(varchar(10),@DATime,120))),6,2);
    Set @DADay   = Substring(Ltrim(Rtrim(Convert(varchar(10),@DATime,120))),9,2);
        Set @DAHour  = Substring(Ltrim(Rtrim(Convert(varchar(10),@DATime,114))),1,2); Set @RowCnt_Year = (Select Count(*) From WenYuanEnergyDataSumByYear Where MeterNo = @MeterNo
     And MeterType = @MeterType And DAYear = @DAYear); If IsNull(@RowCnt_Year,0) = 0
    Begin
    Set @RowCnt_Year = 0;
    End


    If @RowCnt_Year > 0 
    Begin
    Update WenYuanEnergyDataSumByYear Set SumQty = SumQty + @Qty 
    Where MeterNo = @MeterNo And MeterType = @MeterType And DAYear = @DAYear ;
    End
    Else
    Begin
    Insert WenYuanEnergyDataSumByYear(MeterNo,MeterType,DAYear,SumQty,Unit)
    Select @MeterNo,@MeterType,@DAYear,@Qty,@Unit;
    End
        
    ---------- --发生错误回滚事务
    if (@@error <> 0)
    begin
    goto LABROLLBACK
    end --提交事务
    LABCOMMIT:
    if (@@error = 0)
    begin
    COMMIT TRANSACTION
    return(0)
    end
    --以下回滚事务
    LABROLLBACK:
    begin
    ROLLBACK TRANSACTION sp_Datacomputer_TRANS
    return @@error
    endend这个存储过程中没有显示调用“COMMIT TRANSACTION”,数据一样插入和更新到指定表了。
      

  4.   

    这里没有用““goto LABCOMMIT”手动提交事务”,数据一样完成了插入和更新,为什么???
      

  5.   

    你这里有两个部分,一个是处理回滚,一个是处理提交,所以没问题。没有格式化的代码比较难看,看漏了,下面仅帮你格式化而已。ALTER  PROCEDURE [dbo].[sp_DataComputer_WenYuanDatas]
        @DANo CHAR(32) ,--20110112182345207插入时间
        @DATime DATETIME ,--采集时间
        @LogTime DATETIME ,--更新时间
        @MeterType CHAR(4) ,--表具类型
        @MeterNo CHAR(20) ,--表具号码
        @Qty DECIMAL(18, 6) ,--数值
        @Unit CHAR(4) ,--单位
        @outputpar INT = 0 OUTPUT--输出返回值
    AS --带事务存储过程模板
        BEGIN
    --开始事务
            BEGIN TRANSACTION
            SAVE TRANSACTION sp_Datacomputer_TRANS--事务内容,计算时日月数据.
        
            DECLARE @DAYear CHAR(4);
            DECLARE @DAMonth CHAR(2);
            DECLARE @DADay CHAR(2);
            DECLARE @DAHour CHAR(2);        DECLARE @RowCnt_Year INT;
            DECLARE @RowCnt_Month INT;
            DECLARE @RowCnt_Day INT;
            DECLARE @RowCnt_Hour INT;        SET @DAYear = SUBSTRING(LTRIM(RTRIM(CONVERT(VARCHAR(10), @DATime, 120))),
                                    1, 4);
            SET @DAMonth = SUBSTRING(LTRIM(RTRIM(CONVERT(VARCHAR(10), @DATime, 120))),
                                     6, 2);
            SET @DADay = SUBSTRING(LTRIM(RTRIM(CONVERT(VARCHAR(10), @DATime, 120))),
                                   9, 2);
            SET @DAHour = SUBSTRING(LTRIM(RTRIM(CONVERT(VARCHAR(10), @DATime, 114))),
                                    1, 2);        SET @RowCnt_Year = ( SELECT COUNT(*)
                                 FROM   WenYuanEnergyDataSumByYear
                                 WHERE  MeterNo = @MeterNo
                                        AND MeterType = @MeterType
                                        AND DAYear = @DAYear
                               );        IF ISNULL(@RowCnt_Year, 0) = 0
                BEGIN
                    SET @RowCnt_Year = 0;
                END
            IF @RowCnt_Year > 0
                BEGIN
                    UPDATE  WenYuanEnergyDataSumByYear
                    SET     SumQty = SumQty + @Qty
                    WHERE   MeterNo = @MeterNo
                            AND MeterType = @MeterType
                            AND DAYear = @DAYear;
                END
            ELSE
                BEGIN
                    INSERT  WenYuanEnergyDataSumByYear
                            ( MeterNo ,
                              MeterType ,
                              DAYear ,
                              SumQty ,
                              Unit
                            )
                            SELECT  @MeterNo ,
                                    @MeterType ,
                                    @DAYear ,
                                    @Qty ,
                                    @Unit;
                END
        
    ------------发生错误回滚事务
            IF ( @@error <> 0 )
                BEGIN
                    GOTO LABROLLBACK
                END--提交事务
            LABCOMMIT:
            IF ( @@error = 0 )
                BEGIN
                    COMMIT TRANSACTION
                    RETURN(0)
                END
    --以下回滚事务
            LABROLLBACK:
            BEGIN
                ROLLBACK TRANSACTION sp_Datacomputer_TRANS
                RETURN @@error
            END    END
      

  6.   

    这两部分已经符合了显式事务的操作,只是没格式化代码看漏了而已
    -提交事务因为有了这部分,所以显式提交了
    LABCOMMIT:
    if (@@error = 0)
    begin
    COMMIT TRANSACTION
    return(0)
    end
    --以下回滚事务 这部分是显式回滚
    LABROLLBACK:
    begin
    ROLLBACK TRANSACTION sp_Datacomputer_TRANS
    return @@error
    end
      

  7.   


    不用“goto  LABCOMMIT”这样就可以提交吗???   没有用Goto,LABCOMMIT:
    if (@@error = 0)
    begin
    COMMIT TRANSACTION
    return(0)
    end这部分代码也会被执行吗???      并没有”Goto“到这里啊。
      

  8.   

    --提交事务
            LABCOMMIT:
            IF ( @@error = 0 )
                BEGIN
                    COMMIT TRANSACTION
                    RETURN(0)
                END
    --以下回滚事务
            LABROLLBACK:
            BEGIN
                ROLLBACK TRANSACTION sp_Datacomputer_TRANS
                RETURN @@error
            END
    你可以看它的顺序,commit在前,这个存储过程是顺序执行的,也就是说不发升错误的话一定会执行到commit这个,执行完return跳出,就不会执行rollback了,只有在发生错误时才跳过commit这段逻辑进入rollback这里,所以不需要goto,如果你反过来这样写:
    --以下回滚事务
            LABROLLBACK:
            BEGIN
                ROLLBACK TRANSACTION sp_Datacomputer_TRANS
                RETURN @@error
            END
    --提交事务
            LABCOMMIT:
            IF ( @@error = 0 )
                BEGIN
                    COMMIT TRANSACTION
                    RETURN(0)
                END
    那么就有问题了,你可以找个测试环境测测,应该全部rollback
      

  9.   

    这也是我说的不要用goto,会混乱思维的