在非连续步骤上应用 sql 个事务
applying sql transactions on non consecutive steps
我有以下 SQL 语句的场景:
DELETE FROM T1
DELETE FROM T2
DELETE FROM T3
DELETE FROM T4
DELETE FROM T5
在上面的例子中我需要实现:
如果下一个SQL语句失败,将回滚前一个语句,如果成功,它将移动到下一个语句。
但是对于第5步,我需要回滚第3步,按原样提交第4步。
任何意见,请指教。
在SQL 服务器中没有嵌套事务这样的东西。但是您可以通过一些错误处理编排来做到这一点。
如果在 T5 命令上遇到错误,此示例代码只是再次从 T4 重新发出删除命令。
SET NOCOUNT ON;
-- (use temp table, since table vars do not participate in transactions)
CREATE TABLE #T1(C int);
CREATE TABLE #T2(C int);
CREATE TABLE #T3(C int);
CREATE TABLE #T4(C int);
CREATE TABLE #T5(C int);
INSERT INTO #T1 SELECT 1;
INSERT INTO #T2 SELECT 1;
INSERT INTO #T3 SELECT 1;
INSERT INTO #T4 SELECT 1;
INSERT INTO #T5 SELECT 1;
BEGIN TRY
BEGIN TRAN TR1;
DELETE FROM #T1;
DELETE FROM #T2;
DELETE FROM #T3;
DELETE FROM #T4;
--select 1/0 as 'forced error @ stage1';
END TRY
BEGIN CATCH
PRINT 'error @stage1';
PRINT 'rollback @stage1';
ROLLBACK TRAN TR1;
RETURN;
END CATCH
BEGIN TRY
DELETE FROM #T5;
select 1/0 as 'forced error @stage2';
COMMIT TRAN TR1;
END TRY
BEGIN CATCH
PRINT 'error @stage2';
ROLLBACK TRAN TR1;
BEGIN TRY
print 'redo delete T4'
BEGIN TRAN TR2;
DELETE FROM #t4;
--select 1/0 as 'forced error @redo delete';
COMMIT TRAN TR2;
END TRY
BEGIN CATCH
ROLLBACK TRAN TR2;
PRINT 'second chance delete from T4 failed';
END CATCH
END CATCH
select count(*) as count,'T1' as 'table' from #T1
union all
select count(*) as count,'T2' as 'table' from #T2
union all
select count(*) as count,'T3' as 'table' from #T3
union all
select count(*) as count,'T4' as 'table' from #T4
union all
select count(*) as count,'T5' as 'table' from #T5
DROP TABLE #T1;
DROP TABLE #T2;
DROP TABLE #T3;
DROP TABLE #T4;
DROP TABLE #T5;
您可以在 TRY-CATCH 块中使用 SAVE POINTS 和 GOTO 来完成:
这可以实现您在问题中想要的两个目标:
每次取消注释特定的“SELECT 1/0
”语句时对其进行测试:
SET NOCOUNT ON;
CREATE TABLE #T1(ID int);
CREATE TABLE #T2(ID int);
CREATE TABLE #T3(ID int);
CREATE TABLE #T4(ID int);
CREATE TABLE #T5(ID int);
INSERT INTO #T1 SELECT 1;
INSERT INTO #T2 SELECT 1;
INSERT INTO #T3 SELECT 1;
INSERT INTO #T4 SELECT 1;
INSERT INTO #T5 SELECT 1;
BEGIN TRAN
BEGIN TRY
DELETE FROM #T1
--SELECT 1/0
END TRY
BEGIN CATCH
ROLLBACK TRAN
GOTO LAST2
END CATCH
SAVE TRAN pice1
BEGIN TRY
DELETE FROM #T2
--SELECT 1/0
END TRY
BEGIN CATCH
ROLLBACK TRAN
GOTO LAST2
END CATCH
SAVE TRAN pice2
BEGIN TRY
DELETE FROM #T3
--SELECT 1/0
END TRY
BEGIN CATCH
ROLLBACK TRAN pice1
GOTO LAST
END CATCH
SAVE TRAN pice3
BEGIN TRY
DELETE FROM #T4
--SELECT 1/0
END TRY
BEGIN CATCH
ROLLBACK TRAN pice2
GOTO LAST
END CATCH
SAVE TRAN pice4
BEGIN TRY
DELETE FROM #T5
SELECT 1/0
END TRY
BEGIN CATCH
ROLLBACK TRAN pice2
DELETE FROM #T4
GOTO LAST
END CATCH
LAST:
COMMIT TRAN
LAST2:
SELECT COUNT(*) CT,'T1' [TABLE] FROM #T1
UNION
SELECT COUNT(*) CT,'T2' [TABLE] FROM #T2
UNION
SELECT COUNT(*) CT,'T3' [TABLE] FROM #T3
UNION
SELECT COUNT(*) CT,'T4' [TABLE] FROM #T4
UNION
SELECT COUNT(*) CT,'T5' [TABLE] FROM #T5
DROP TABLE #T1;
DROP TABLE #T2;
DROP TABLE #T3;
DROP TABLE #T4;
DROP TABLE #T5;
我有以下 SQL 语句的场景:
DELETE FROM T1
DELETE FROM T2
DELETE FROM T3
DELETE FROM T4
DELETE FROM T5
在上面的例子中我需要实现:
如果下一个SQL语句失败,将回滚前一个语句,如果成功,它将移动到下一个语句。
但是对于第5步,我需要回滚第3步,按原样提交第4步。
任何意见,请指教。
在SQL 服务器中没有嵌套事务这样的东西。但是您可以通过一些错误处理编排来做到这一点。
如果在 T5 命令上遇到错误,此示例代码只是再次从 T4 重新发出删除命令。
SET NOCOUNT ON;
-- (use temp table, since table vars do not participate in transactions)
CREATE TABLE #T1(C int);
CREATE TABLE #T2(C int);
CREATE TABLE #T3(C int);
CREATE TABLE #T4(C int);
CREATE TABLE #T5(C int);
INSERT INTO #T1 SELECT 1;
INSERT INTO #T2 SELECT 1;
INSERT INTO #T3 SELECT 1;
INSERT INTO #T4 SELECT 1;
INSERT INTO #T5 SELECT 1;
BEGIN TRY
BEGIN TRAN TR1;
DELETE FROM #T1;
DELETE FROM #T2;
DELETE FROM #T3;
DELETE FROM #T4;
--select 1/0 as 'forced error @ stage1';
END TRY
BEGIN CATCH
PRINT 'error @stage1';
PRINT 'rollback @stage1';
ROLLBACK TRAN TR1;
RETURN;
END CATCH
BEGIN TRY
DELETE FROM #T5;
select 1/0 as 'forced error @stage2';
COMMIT TRAN TR1;
END TRY
BEGIN CATCH
PRINT 'error @stage2';
ROLLBACK TRAN TR1;
BEGIN TRY
print 'redo delete T4'
BEGIN TRAN TR2;
DELETE FROM #t4;
--select 1/0 as 'forced error @redo delete';
COMMIT TRAN TR2;
END TRY
BEGIN CATCH
ROLLBACK TRAN TR2;
PRINT 'second chance delete from T4 failed';
END CATCH
END CATCH
select count(*) as count,'T1' as 'table' from #T1
union all
select count(*) as count,'T2' as 'table' from #T2
union all
select count(*) as count,'T3' as 'table' from #T3
union all
select count(*) as count,'T4' as 'table' from #T4
union all
select count(*) as count,'T5' as 'table' from #T5
DROP TABLE #T1;
DROP TABLE #T2;
DROP TABLE #T3;
DROP TABLE #T4;
DROP TABLE #T5;
您可以在 TRY-CATCH 块中使用 SAVE POINTS 和 GOTO 来完成:
这可以实现您在问题中想要的两个目标:
每次取消注释特定的“SELECT 1/0
”语句时对其进行测试:
SET NOCOUNT ON;
CREATE TABLE #T1(ID int);
CREATE TABLE #T2(ID int);
CREATE TABLE #T3(ID int);
CREATE TABLE #T4(ID int);
CREATE TABLE #T5(ID int);
INSERT INTO #T1 SELECT 1;
INSERT INTO #T2 SELECT 1;
INSERT INTO #T3 SELECT 1;
INSERT INTO #T4 SELECT 1;
INSERT INTO #T5 SELECT 1;
BEGIN TRAN
BEGIN TRY
DELETE FROM #T1
--SELECT 1/0
END TRY
BEGIN CATCH
ROLLBACK TRAN
GOTO LAST2
END CATCH
SAVE TRAN pice1
BEGIN TRY
DELETE FROM #T2
--SELECT 1/0
END TRY
BEGIN CATCH
ROLLBACK TRAN
GOTO LAST2
END CATCH
SAVE TRAN pice2
BEGIN TRY
DELETE FROM #T3
--SELECT 1/0
END TRY
BEGIN CATCH
ROLLBACK TRAN pice1
GOTO LAST
END CATCH
SAVE TRAN pice3
BEGIN TRY
DELETE FROM #T4
--SELECT 1/0
END TRY
BEGIN CATCH
ROLLBACK TRAN pice2
GOTO LAST
END CATCH
SAVE TRAN pice4
BEGIN TRY
DELETE FROM #T5
SELECT 1/0
END TRY
BEGIN CATCH
ROLLBACK TRAN pice2
DELETE FROM #T4
GOTO LAST
END CATCH
LAST:
COMMIT TRAN
LAST2:
SELECT COUNT(*) CT,'T1' [TABLE] FROM #T1
UNION
SELECT COUNT(*) CT,'T2' [TABLE] FROM #T2
UNION
SELECT COUNT(*) CT,'T3' [TABLE] FROM #T3
UNION
SELECT COUNT(*) CT,'T4' [TABLE] FROM #T4
UNION
SELECT COUNT(*) CT,'T5' [TABLE] FROM #T5
DROP TABLE #T1;
DROP TABLE #T2;
DROP TABLE #T3;
DROP TABLE #T4;
DROP TABLE #T5;