【发布时间】:2015-05-11 15:27:33
【问题描述】:
我是第一次使用事务,所以我可能会问一个愚蠢的问题。
我想在 3 个表中插入数据:
Table1(p1,p2,p3)
Table2(q1,q2)
Table3(t3,fk1,fk2)
例如,如果出现问题并且无法将数据插入Table2,则来自Table1 的数据不会丢失并且Table3 保持不变(反之亦然)。
到目前为止,我已经尝试了两个版本,但没有一个令人满意。
版本 1:
CREATE PROCEDURE InsertInto(@p1,@p2,@p3,@q1,@q2,@t3))
AS BEGIN
BEGIN TRAN
SET XACT_ABORT OFF
SAVE TRANSACTION point1
BEGIN TRY
DECLARE @fk1 INT
INSERT INTO Table1 VALUES (@p1,@p2,@p3)
SELECT @fk1 = Table1.Id FROM Table1 WHERE Table1.p1 = @p1
SAVE TRANSACTION point2
BEGIN TRY
DECLARE @fk2 INT
INSERT INTO Table2 VALUES (@q1,@q2)
SELECT @fk2 = Table2.Id FROM Table2 WHERE Table2.q1 = @q1
SAVE TRANSACTION point3
BEGIN TRY
INSERT INTO Table3 VALUES (@t3, @fk1, @fk2)
COMMIT TRAN
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION point3
COMMIT TRAN
END CATCH
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION point2
COMMIT TRAN
END CATCH
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION point1
COMMIT TRAN
END CATCH
END
但是如果不能在Table1 中插入数据,那么Table2 的可能数据就会丢失,我不想丢失任何东西。所以,我尝试了拆分它。
版本 2:
CREATE PROCEDURE InsertInto(@p1,@p2,@p3,@q1,@q2,@t3)
AS
BEGIN
BEGIN TRAN
SET XACT_ABORT OFF
SAVE TRANSACTION point1
BEGIN TRY
DECLARE @fk1 INT
INSERT INTO Table1 VALUES (@p1,@p2,@p3)
SELECT @fk1 = Table1.Id FROM Table1 WHERE Table1.p1 = @p1
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION point1
COMMIT TRAN
END CATCH
SAVE TRANSACTION point2
BEGIN TRY
DECLARE @fk2 INT
INSERT INTO Table2 VALUES (@q1,@q2)
SELECT @fk2 = Table2.Id FROM Table2 WHERE Table2.q1 = @q1
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION point2
COMMIT TRAN
END CATCH
SAVE TRANSACTION point3
BEGIN TRY
INSERT INTO Table3 VALUES (@t3,@fk1,@fk2)
COMMIT TRAN
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION point3
COMMIT TRAN
END CATCH
END
但如果插入 Table2 失败,我会得到:
(受影响的 1 行)
(0 行受影响)
消息 628,级别 16,状态 0,过程 InsertInto,第 26 行(第二个 BEGIN CATCH)
没有活动事务时无法发出 SAVE TRANSACTION。
我怎样才能做到这一点?
【问题讨论】:
-
这里似乎根本不应该使用保存点,而只是在每一步之后提交,然后开始一个新事务。你能澄清你为什么使用保存点吗?也许您的代码的某些用途只是从问题中不清楚。
-
我想学习如何使用保存点,以免在事务期间丢失数据。
标签: sql sql-server transactions savepoints