2011-02-18 105 views
1

我正在尝试使用事务编写一个sproc。任何人都可以告诉我,下面的代码是否会有问题,或者它是否能按预期工作?第一次尝试进行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 
+1

您正在使用哪个版本的SQL Server? – 2011-02-18 09:19:30

回答

0

没有与程序的几个问题:

  • ,除非它确实表明了错误,则不应评估的行数。当没有数据被删除时,不需要回滚。
  • 您的代码不是线程安全的。该MetricMeterCount查询应改为是为了防止其他线程在执行您的选择&之间的删除删除的执行:

    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,失败返回值为负数。

1

如果您正在使用SQL Server 2005+,我会建议使用比较和TRY...CATCH (Transact-SQL)来看看部分[B.使用TRY ... CATCH在交易]

这将不胜简化你的程序。

相关问题