在错误期间删除事务仍然发生吗?

huangapple go评论115阅读模式
英文:

Delete within transaction during error still occurs?

问题

BEGIN TRANSACTION
开始事务

DELETE FROM TableA WHERE Col1 = 'someval'
从TableA中删除满足条件Col1 = 'someval'的记录

INSERT INTO TableB (col1,col2,col3,coln)
向TableB插入数据,列包括col1、col2、col3和coln
SELECT col1,col2,col3,coln FROM SomeOtherTable
从SomeOtherTable中选择数据,列包括col1、col2、col3和coln

COMMIT TRANSACTION
提交事务

I was running into a scenario where the Insert into failed due to some formatting issues, but I also noticed the Delete succeeded. I thought the transaction would have prevented this? What am I missing. Obviously this is pseudo-code, but the real table names and code are nearly as simple. What the heck could have lead to this?

我遇到了一个情况,插入操作因为某种格式问题失败了,但我也注意到删除操作成功了。我以为事务应该阻止了这种情况发生?我漏掉了什么?显然这是伪代码,但真实的表名和代码几乎一样简单。到底是什么导致了这种情况?

I suppose one solution would be to add try/catch around the insert and rollback on error, but I was under the assumption that it would auto roll back.

我想一个解决方案是在插入操作周围添加try/catch,并在出现错误时回滚,但我曾以为它会自动回滚。

英文:
  1. BEGIN TRANSACTION
  2. DELETE FROM TableA WHERE Col1 = 'someval'
  3. INSERT INTO TableB (col1,col2,col3,coln)
  4. SELECT col1,col2,col3,coln FROM SomeOtherTable
  5. COMMIT TRANSACTION

I was running into a scenario where the Insert into failed due to some formatting issues, but I also noticed the Delete succeeded. I thought the transaction would have prevented this? What am I missing. Obviously this is pseudo-code, but the real table names and code are nearly as simple. What the heck could have lead to this?

I suppose one solution would be to add try/catch around the insert and rollback on error, but I was under the assumption that it would auto roll back.

答案1

得分: 4

以下是您要翻译的内容:

"事务只是意味着任何更改都会在同一时间全部提交。如果遇到非批处理中止错误,那么在到达COMMIT时之前的任何更改(以及之后发生的任何更改)仍将被提交。

例如,考虑以下表格和示例数据:

  1. CREATE TABLE dbo.SomeTableID int IDENTITY1,1),
  2. SomeDate日期,
  3. SomeString varchar3));
  4. GO
  5. INSERT INTO dbo.SomeTableSomeDateSomeString
  6. VALUESGETDATE(),'abc'),
  7. GETDATE(),'def'),
  8. GETDATE(),'ghi');
  9. GO

现在我将DELETEINSERT 2行,每次操作影响1行,都在事务内。其中一个我将提供无效日期,即中止错误,另一个是将导致截断的值,即非中止错误:

  1. BEGIN TRANSACTION
  2. DELETE FROM dbo.SomeTable
  3. WHERE ID = 1
  4. INSERT INTO dbo.SomeTableSomeDateSomeString
  5. VALUES'20231301''xyz'
  6. COMMIT;
  7. GO
  8. BEGIN TRANSACTION
  9. DELETE FROM dbo.SomeTable
  10. WHERE ID = 2
  11. INSERT INTO dbo.SomeTableSomeDateSomeString
  12. VALUES'20231201''mnop';
  13. COMMIT;
  14. GO

请注意您收到的结果;ID 1 仍然存在(批量中止),但ID 2 不再存在(批次未中止):

ID SomeDate SomeString
1 2023-08-04 abc
3 2023-08-04 ghi
4 2023-08-04 jkl

如果要在遇到错误时中止事务,请使用XACT_ABORT

  1. SET XACT_ABORT ON;
  2. BEGIN TRANSACTION
  3. DELETE FROM dbo.SomeTable
  4. WHERE ID = 3
  5. INSERT INTO dbo.SomeTableSomeDateSomeString
  6. VALUES'20231301''xyz'
  7. COMMIT;
  8. GO
  9. SET XACT_ABORT ON;
  10. BEGIN TRANSACTION
  11. DELETE FROM dbo.SomeTable
  12. WHERE ID = 4
  13. INSERT INTO dbo.SomeTableSomeDateSomeString
  14. VALUES'20231201''mnop';
  15. COMMIT;
  16. GO

请注意,ID 4 现在也没有被DELETE。"

英文:

The transaction simply means that any changes are all committed at the same time. If you encounter a non-batch aborting error then any prior changes (and any that occur afterwards) will still be committed when you reach the COMMIT.

For example, take the following table and sample data:

  1. CREATE TABLE dbo.SomeTable (ID int IDENTITY(1,1),
  2. SomeDate date,
  3. SomeString varchar(3));
  4. GO
  5. INSERT INTO dbo.SomeTable (SomeDate, SomeString)
  6. VALUES(GETDATE(),'abc'),
  7. (GETDATE(),'def'),
  8. (GETDATE(),'ghi');
  9. GO

Now I'm going to DELETE and INSERT 2 rows, effecting 1 row with each operation inside a transaction. In one I'll provide an invalid date, an aborting error, and in the other a value that will cause truncation, a non-aborting error:

  1. BEGIN TRANSACTION
  2. DELETE FROM dbo.SomeTable
  3. WHERE ID = 1
  4. INSERT INTO dbo.SomeTable (SomeDate, SomeString)
  5. VALUES('20231301','xyz')
  6. COMMIT;
  7. GO
  8. BEGIN TRANSACTION
  9. DELETE FROM dbo.SomeTable
  10. WHERE ID = 2
  11. INSERT INTO dbo.SomeTable (SomeDate, SomeString)
  12. VALUES('20231201','mnop');
  13. COMMIT;
  14. GO

Notice the results you get back; ID 1 remains (batched aborted) but ID 2 doesn't (batch wasn't aborted):

ID SomeDate SomeString
1 2023-08-04 abc
3 2023-08-04 ghi
4 2023-08-04 jkl

If you want the transaction to be aborted when an error is encountered then use XACT_ABORT:

  1. SET XACT_ABORT ON;
  2. BEGIN TRANSACTION
  3. DELETE FROM dbo.SomeTable
  4. WHERE ID = 3
  5. INSERT INTO dbo.SomeTable (SomeDate, SomeString)
  6. VALUES('20231301','xyz')
  7. COMMIT;
  8. GO
  9. SET XACT_ABORT ON;
  10. BEGIN TRANSACTION
  11. DELETE FROM dbo.SomeTable
  12. WHERE ID = 4
  13. INSERT INTO dbo.SomeTable (SomeDate, SomeString)
  14. VALUES('20231201','mnop');
  15. COMMIT;
  16. GO

Notice that ID 4 is not DELETEd now too.

huangapple
  • 本文由 发表于 2023年8月4日 21:54:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/76836598.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定