英文:
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
现在我将DELETE
和INSERT
2行,每次操作影响1行,都在事务内。其中一个我将提供无效日期,即中止错误,另一个是将导致截断的值,即非中止错误:
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
请注意您收到的结果;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.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
请注意,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 DELETE
d now too.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论