我是第一次使用事务,所以我可能会问一个愚蠢的问题。
我想在 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
但是如果 Insert into Table2 失败,我会得到这个:
(1 行受影响)
(0 行受影响)
消息 628,级别 16,状态 0,过程 InsertInto,第 26 行(第二个 BEGIN CATCH)
当没有活动事务时无法发出 SAVE TRANSACTION。
我怎样才能做到这一点?