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

Is it necessary to use a transaction if other statements are dependent on the first?

长期以来,我一直忽略使用 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

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

其次,无论出于何种原因,就正确实施而言,交易让我感到困惑。我在这里看到一个例子,那里看到另一个例子,我刚刚打开 adventureworks 找到另一个带有 try、catch、rollback 等的例子。

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

如果是,应该如何正确实施?根据我见过的例子:

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 中才需要回滚?

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

为确保这一点,您应该按照上一个示例中的说明将所有语句包装在 begin transaction 中。重要的是要有一个捕获,以便明确回滚任何半完成的事务并尽快释放资源(由事务使用)。

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

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

如果您想在 SP 中处理交易,您的第三个示例代码是正确的。要return一个错误,你可以试试:

RETURN @@ERROR

回滚后。另外,请查看:

set xact_abort on

如:SQL Server - transactions roll back on error?