Tsql 存储过程事务的第一次尝试

Tsql 存储过程事务的第一次尝试,tsql,Tsql,我正在尝试使用事务编写存储过程。有谁能告诉我下面的代码是否会有问题,或者它是否能按预期工作 ALTER procedure [dbo].[DeleteMetricMeter] ( @SectionID int, @MetricMeterID int, @Result bit output ) as declare @MetricMeterCount int declare @err int declare @rowcount int set xact_abort

我正在尝试使用事务编写存储过程。有谁能告诉我下面的代码是否会有问题,或者它是否能按预期工作

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

如果您使用的是Sql Server 2005+,我建议您使用并查看[B.在事务中使用TRY…CATCH]


这将大大简化您的过程。

如果您使用的是Sql Server 2005+,我建议您使用并查看[B.在事务中使用TRY…CATCH]


这将大大简化您的程序。

该程序存在一些问题:

您不应该计算rowcount,除非它确实指示错误。如果没有删除数据,则无需回滚。 您的代码不是线程安全的。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,失败的返回值应为负数。

该过程存在一些问题:

您不应该计算rowcount,除非它确实指示错误。如果没有删除数据,则无需回滚。 您的代码不是线程安全的。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,失败返回值应为负数。

您使用的是哪个版本的SQL Server?您使用的是哪个版本的SQL Server?