如果其他语句依赖于第一个语句,是否有必要使用事务?

时间:2015-03-16 21:41:57

标签: sql-server transactions sql-server-2012

很长一段时间,我省略了使用SQL事务,主要是出于无知。

但是,让我说我有这样的程序:

CREATE PROCEDURE CreatePerson

AS
BEGIN

declare @NewPerson INT

INSERT INTO PersonTable ( Columns... ) VALUES ( @Parameters... )
SET @NewPerson = SCOPE_IDENTITY()

INSERT INTO AnotherTable ( @PersonID, CreatedOn ) VALUES ( @NewPerson, getdate() )

END
GO

在上面的示例中,第二个插入依赖于第一个插入,因为如果第一个插入失败,它将失败。

其次,无论出于何种原因,只要正确实施,交易就会让我感到困惑。我在这里看到一个例子,另一个在那里,我只是打开冒险工程,找到另一个尝试,捕获,回滚等的例子。

我没有记录错误。我应该在这里使用交易吗?这值得么?

如果是这样,应该如何正确实施?基于我见过的例子:

CREATE PROCEURE CreatePerson

AS
BEGIN TRANSACTION

....

COMMIT TRANSACTION
GO

或者:

CREATE PROCEDURE CreatePerson

AS
BEGIN
    BEGIN TRANSACTION

    COMMIT TRANSACTION
END
GO

或者:

CREATE PROCEDURE CreatePerson

AS
BEGIN

BEGIN TRY
    BEGIN TRANSACTION

    ...

    COMMIT TRANSACTION
END TRY
BEGIN CATCH
    IF @@TRANCOUNT > 0
    BEGIN
        ROLLBACK TRANSACTION
    END
END CATCH
END

最后,在我的真实代码中,我有更多像5个单独的插入所有基于新生成的人员ID。如果你是我,你会怎么做?这个问题可能是多余的或重复的,但无论出于何种原因,我似乎无法在我的脑海中调和处理这个问题的最佳方法。

另一个混乱的领域是回滚。如果必须将事务作为单个操作单元提交,那么如果您不使用回滚会发生什么?或者仅在类似于vb.net/c#错误处理的Try / Catch中需要回滚?

2 个答案:

答案 0 :(得分:1)

您可能忽略了这一点:事务假设将一组单独的操作合并为一个,因此如果一个失败,您可以回滚并且数据库将保持不变,就好像什么都没发生一样。

如果您要在商店中保存购买的详细信息,则更容易看到。您保存客户的数据(如姓名或地址),但不知何故,您错过了详细信息(服务器崩溃)。所以现在你知道John Doe买了东西,但你不知道是什么。您数据完整性受到威胁。

如果要处理SP中的事务,则第三个示例代码是正确的。要返回错误,您可以尝试:

RETURN @@ERROR

ROLLBACK之后。另外,请查看:

set xact_abort on

如:SQL Server - transactions roll back on error?

答案 1 :(得分:0)

如果第一次插入成功而第二次插入失败,则会使数据库处于错误状态,因为SQL Server无法读懂您的想法。它将在数据库中保留第一个插入(更改),即使您可能希望它全部被tosucceed或全部失败。

为了确保这一点,您应该将所有语句包装在begin transaction中,如上例所示。拥有一个catch的重要性,因此任何一半完成的事务都会被显式回滚,并且资源(由事务使用)会尽快释放。