第一次尝试进行sproc交易

时间:2011-02-18 09:15:12

标签: tsql

我正在尝试用事务编写一个sproc。有人可以告诉我下面的代码是否有任何问题,或者它是否能按预期工作?

ALTER procedure [dbo].[DeleteMetricMeter]

(
    @SectionID int,
    @MetricMeterID int,
    @Result bit output
)

as

declare @MetricMeterCount int
declare @err int
declare @rowcount int

set xact_abort on

begin tran

select @MetricMeterCount = count(*) from luMetricMeters
where fkSectionID = @SectionID

select @err = @@error, @rowcount = @@rowcount 

if (@err <> 0) or (@rowcount = 0)
begin
    goto on_error           
end

delete from luMetricMeterList
where pkMetricMeterID = @MetricMeterID

select @err = @@error, @rowcount = @@rowcount 

if (@err <> 0) or (@rowcount = 0)
begin
    goto on_error           
end 

delete from luMetricMeters
where pkMetricMeterID = @MetricMeterID

select @err = @@error, @rowcount = @@rowcount 

if (@err <> 0) or (@rowcount = 0)
begin
    goto on_error           
end

if (@MetricMeterCount = 1)
begin
    delete from luMetricSections
    where pkSectionID = @SectionID

    select @err = @@error, @rowcount = @@rowcount 

    if (@err <> 0) or (@rowcount = 0)
    begin
        goto on_error           
    end
end

commit tran
set @result = 1
return @result

on_error:
    rollback tran
    set @result = 0
    return @result

2 个答案:

答案 0 :(得分:1)

如果您使用的是Sql Server 2005+,我建议您使用TRY...CATCH (Transact-SQL),并查看[ B]部分。在交易中使用TRY ... CATCH ]

这将 GREATLY 简化您的程序。

答案 1 :(得分:0)

该程序存在一些问题:

  • 除非确实指出错误,否则不应评估rowcount。如果没有删除数据,则无需回滚。
  • 您的代码不是线程安全的。应将MetricMeterCount查询更改为此选项,以防止其他线程在您的select和amp;之间执行删除操作。执行删除:

    select @MetricMeterCount = count(*) 
      from luMetricMeters with (xlock, serializable)
     where fkSectionID = @SectionID  
    

我会写这样的代码:

ALTER procedure [dbo].[DeleteMetricMeter]

(
    @SectionID int,
    @MetricMeterID int,
    @Result bit output
)

as

DECLARE @MetricMeterCount int
DECLARE @err int
DECLARE @rowcount int

SET xact_abort ON

BEGIN TRAN

DELETE FROM luMetricMeterList 
 WHERE pkMetricMeterID = @MetricMeterID

SELECT @err = @@error

IF (@err <> 0) 
    GOTO on_error           

DELETE FROM luMetricMeters
 WHERE pkMetricMeterID = @MetricMeterID

SELECT @err = @@error

IF (@err <> 0) 
    GOTO on_error           

IF EXISTS (SELECT * 
             FROM luMetricMeters WITH (xlock, serializable) 
            WHERE fkSectionID = @SectionID)
BEGIN
    DELETE FROM luMetricSections 
     WHERE pkSectionID = @SectionID

    SELECT @err = @@error
    IF (@err <> 0) 
        GOTO on_error           
END

COMMIT TRAN

RETURN (0)

on_error:
    ROLLBACK TRAN
    RETURN (-1)
GO

注意:成功时返回值应为0,失败时返回负值。