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

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

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,并在出现错误时回滚,但我曾以为它会自动回滚。

英文:
BEGIN TRANSACTION
   DELETE FROM TableA WHERE Col1 = 'someval'
   INSERT INTO TableB (col1,col2,col3,coln)
   SELECT col1,col2,col3,coln FROM SomeOtherTable

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时之前的任何更改(以及之后发生的任何更改)仍将被提交。

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

CREATE TABLE dbo.SomeTable(ID int IDENTITY(1,1),
                            SomeDate日期,
                            SomeString varchar(3));
GO

INSERT INTO dbo.SomeTable(SomeDate,SomeString)
VALUES(GETDATE(),'abc'),
      (GETDATE(),'def'),
      (GETDATE(),'ghi');
GO

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

BEGIN TRANSACTION
    DELETE FROM dbo.SomeTable
    WHERE ID = 1
    INSERT INTO dbo.SomeTableSomeDateSomeString
    VALUES'20231301''xyz'
COMMIT;
GO

BEGIN TRANSACTION
    DELETE FROM dbo.SomeTable
    WHERE ID = 2
    INSERT INTO dbo.SomeTableSomeDateSomeString
    VALUES'20231201''mnop';
COMMIT;
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

SET XACT_ABORT ON;

BEGIN TRANSACTION
    DELETE FROM dbo.SomeTable
    WHERE ID = 3
    INSERT INTO dbo.SomeTableSomeDateSomeString
    VALUES'20231301''xyz'
COMMIT;
GO

SET XACT_ABORT ON;

BEGIN TRANSACTION
    DELETE FROM dbo.SomeTable
    WHERE ID = 4
    INSERT INTO dbo.SomeTableSomeDateSomeString
    VALUES'20231201''mnop';
COMMIT;
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:

CREATE TABLE dbo.SomeTable (ID int IDENTITY(1,1),
                            SomeDate date,
                            SomeString varchar(3));
GO

INSERT INTO dbo.SomeTable (SomeDate, SomeString)
VALUES(GETDATE(),'abc'),
      (GETDATE(),'def'),
      (GETDATE(),'ghi');
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:

BEGIN TRANSACTION
    DELETE FROM dbo.SomeTable
    WHERE ID = 1
    INSERT INTO dbo.SomeTable (SomeDate, SomeString)
    VALUES('20231301','xyz')
COMMIT;
GO

BEGIN TRANSACTION
    DELETE FROM dbo.SomeTable
    WHERE ID = 2
    INSERT INTO dbo.SomeTable (SomeDate, SomeString)
    VALUES('20231201','mnop');
COMMIT;
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:

SET XACT_ABORT ON;

BEGIN TRANSACTION
    DELETE FROM dbo.SomeTable
    WHERE ID = 3
    INSERT INTO dbo.SomeTable (SomeDate, SomeString)
    VALUES('20231301','xyz')
COMMIT;
GO

SET XACT_ABORT ON;

BEGIN TRANSACTION
    DELETE FROM dbo.SomeTable
    WHERE ID = 4
    INSERT INTO dbo.SomeTable (SomeDate, SomeString)
    VALUES('20231201','mnop');
COMMIT;
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:

确定