2011-02-18 63 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在交易]

這將不勝簡化你的程序。