很长一段时间,我省略了使用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中需要回滚?
答案 0 :(得分:1)
您可能忽略了这一点:事务假设将一组单独的操作合并为一个,因此如果一个失败,您可以回滚并且数据库将保持不变,就好像什么都没发生一样。
如果您要在商店中保存购买的详细信息,则更容易看到。您保存客户的数据(如姓名或地址),但不知何故,您错过了详细信息(服务器崩溃)。所以现在你知道John Doe买了东西,但你不知道是什么。您数据完整性受到威胁。
如果要处理SP中的事务,则第三个示例代码是正确的。要返回错误,您可以尝试:
RETURN @@ERROR
ROLLBACK之后。另外,请查看:
set xact_abort on
答案 1 :(得分:0)
如果第一次插入成功而第二次插入失败,则会使数据库处于错误状态,因为SQL Server无法读懂您的想法。它将在数据库中保留第一个插入(更改),即使您可能希望它全部被tosucceed或全部失败。
为了确保这一点,您应该将所有语句包装在begin transaction中,如上例所示。拥有一个catch的重要性,因此任何一半完成的事务都会被显式回滚,并且资源(由事务使用)会尽快释放。