如何防止未来的批次完成时出错并回滚?

发布于 2024-11-19 19:15:31 字数 1495 浏览 0 评论 0原文

如果我有以下 SQL 查询

CREATE TABLE #t1
    (a INT NOT NULL PRIMARY KEY);
SET XACT_ABORT ON
go

BEGIN TRANSACTION
INSERT INTO #t1 VALUES (1);
INSERT INTO #t1 VALUES (2);
INSERT INTO #t1 VALUES (3);
INSERT INTO #t1 VALUES (2); -- PK violation error
go

INSERT INTO #t1 VALUES (4);
go

COMMIT TRANSACTION

SET XACT_ABORT OFF

当我运行查询时我得到这个输出

(1 行受影响)

(1 行受影响)

(1 行受影响)消息 2627,级别 14,状态 1,第 7 行 主键约束“PK_#t1______66D536B1”。无法插入 对象“dbo.#t1”中的重复键。

(1 行受影响)消息 102,级别 15,状态 1,第 8 行不正确 '#t1' 附近的语法。

#t1 的值是

a
-----------
4

我需要做什么才能使脚本中止并且不运行第二批?

编辑:

尝试了 JNK 的解决方案

begin try
BEGIN TRANSACTION
INSERT INTO #t1 VALUES (1)
INSERT INTO #t1 VALUES (2)
INSERT INTO #t1 VALUES (3)
INSERT INTO #t1 VALUES (2) -- PK violation error
go

INSERT INTO #t1 VALUES (4)
go

COMMIT TRANSACTION

end try
begin catch 
IF @@trancount > 0 Rollback

END catch

select * from #t1

truncate table #t1

但是我得到了这个输出

Msg 102, Level 15, State 1, Line 6
Incorrect syntax near ')'.

(1 row(s) affected)
Msg 102, Level 15, State 1, Line 5
Incorrect syntax near 'begin'.
Msg 102, Level 15, State 1, Line 8
Incorrect syntax near 'END'.

并且该表仍然包含 4 之后

EDIT2:

try catch 的错误是因为 GO 语句,我需要将其用于我的真实脚本这个测试用例。所以看来 try/catch 不适用于这种情况。

If I have the following SQL query

CREATE TABLE #t1
    (a INT NOT NULL PRIMARY KEY);
SET XACT_ABORT ON
go

BEGIN TRANSACTION
INSERT INTO #t1 VALUES (1);
INSERT INTO #t1 VALUES (2);
INSERT INTO #t1 VALUES (3);
INSERT INTO #t1 VALUES (2); -- PK violation error
go

INSERT INTO #t1 VALUES (4);
go

COMMIT TRANSACTION

SET XACT_ABORT OFF

When I run the query I get this output

(1 row(s) affected)

(1 row(s) affected)

(1 row(s) affected) Msg 2627, Level 14, State 1, Line 7 Violation of
PRIMARY KEY constraint 'PK_#t1______66D536B1'. Cannot insert
duplicate key in object 'dbo.#t1'.

(1 row(s) affected) Msg 102, Level 15, State 1, Line 8 Incorrect
syntax near '#t1'.

And the value of #t1 is

a
-----------
4

What do I need to do so the script will abort out and not run the second batch?

EDIT:

Tried JNK's solution

begin try
BEGIN TRANSACTION
INSERT INTO #t1 VALUES (1)
INSERT INTO #t1 VALUES (2)
INSERT INTO #t1 VALUES (3)
INSERT INTO #t1 VALUES (2) -- PK violation error
go

INSERT INTO #t1 VALUES (4)
go

COMMIT TRANSACTION

end try
begin catch 
IF @@trancount > 0 Rollback

END catch

select * from #t1

truncate table #t1

However I get this output

Msg 102, Level 15, State 1, Line 6
Incorrect syntax near ')'.

(1 row(s) affected)
Msg 102, Level 15, State 1, Line 5
Incorrect syntax near 'begin'.
Msg 102, Level 15, State 1, Line 8
Incorrect syntax near 'END'.

And the table still contains a 4 afterward

EDIT2:

the errors with the try catch is because of the GO statement, which I need to have for my real script instead of this test case. so it appears try/catch will not work for this case.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

清浅ˋ旧时光 2024-11-26 19:15:31

添加错误处理:

BEGIN TRY
<your query>
END TRY
BEGIN CATCH

IF @@TRANCOUNT > 0 ROLLBACK    

<other error reporting processes>

END CATCH

ROLLBACK 是可选的,它将撤消在错误发生之前完成的任何插入。您还可以添加多个事务,因此,如果说前 3 个插入稍后与其他一些内容无关,请将它们包装在一个事务中并提交它,然后再为不相关的过程创建另一个事务。

Add error handling:

BEGIN TRY
<your query>
END TRY
BEGIN CATCH

IF @@TRANCOUNT > 0 ROLLBACK    

<other error reporting processes>

END CATCH

The ROLLBACK is optional and will undo any inserts that completed before the error occured. You can also add multiple transactions, so if say the first 3 inserts are independent of some other stuff later on, wrap those in a transaction and commit it, then have another tran later on for the unrelated process.

美煞众生 2024-11-26 19:15:31
begin try
   begin transaction

    INSERT INTO #t1 VALUES (1);
    INSERT INTO #t1 VALUES (2);
    INSERT INTO #t1 VALUES (3);
    INSERT INTO #t1 VALUES (2); 
    INSERT INTO #t1 VALUES (4);

   commit
end try
begin catch
    if @@trancount > 0
        rollback

    declare @errmsg nvarchar(4000), @errseverity int
    select @errmsg = error_message(), @errseverity = error_severity()

    raiserror(@errmsg, @errseverity, 1)
end catch

来自 MSDN:

将 GO 解释为应将当前批次的 Transact-SQL 语句发送到 SQL Server 实例的信号。当前批次的语句由自上次 GO 以来输入的所有语句组成,或者自临时会话或脚本开始(如果这是第一个 GO)以来输入的所有语句组成。

Transact-SQL 语句不能与 GO 命令占用同一行。但是,该行可以包含注释。

begin try
   begin transaction

    INSERT INTO #t1 VALUES (1);
    INSERT INTO #t1 VALUES (2);
    INSERT INTO #t1 VALUES (3);
    INSERT INTO #t1 VALUES (2); 
    INSERT INTO #t1 VALUES (4);

   commit
end try
begin catch
    if @@trancount > 0
        rollback

    declare @errmsg nvarchar(4000), @errseverity int
    select @errmsg = error_message(), @errseverity = error_severity()

    raiserror(@errmsg, @errseverity, 1)
end catch

From MSDN:
"
interpret GO as a signal that they should send the current batch of Transact-SQL statements to an instance of SQL Server. The current batch of statements is composed of all statements entered since the last GO, or since the start of the ad hoc session or script if this is the first GO.

A Transact-SQL statement cannot occupy the same line as a GO command. However, the line can contain comments.
"

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文