我正在使用sql server 2012
这是我的疑问:
begin try
select 1/0
end try
begin catch
select 'div by 0'
end catch
它返回2个不同的结果:
但预期的结果是div by 0
?因为尝试失败后的控制转移到了捕获?
那为什么会返回2个结果?
答案 0 :(得分:3)
这里重要的是,divis为零是一个运行时错误,终止语句到达它的位置。语句select 1/0
本身是完全有效的,并且可以创建结果集,它是在表达式1/0
的评估期间,用于发生错误的第一行和唯一一行数据。如果你稍微扩展你的例子,你会看到更好的;
begin try
declare @t table (i float)
insert @t values (2),(1),(0),(-1)
select 1/i as r from @t
end try
begin catch
select 'div by 0'
end catch
在生成的第一个结果集中,您现在将看到2行,然后发生除零,并且不再生成任何行。值得注意的是“受影响的行”消息。
(4 row(s) affected)
(0 row(s) affected)
(1 row(s) affected)
4行来自insert @t
,1行来自select 'div by 0'
。终止的select 1/i as r from @t
报告0行,尽管事实上我们可以看到2行被返回到SSMS。这里发生的是,尽管创建了结果集并且行返回到客户端,但SQL Server数据库引擎支持ACID属性,并且由于select 1/i as r from @t
没有完全完成,因此它被回滚(选择是原子的)。 SSMS可能已收到一些行,但就SQL Server而言,没有生成任何行。再次扩展您的示例以捕获行演示了这一点;
declare @t table (i float)
declare @t2 table (i float)
insert @t values (2),(1),(0),(-1)
begin try
insert @t2 select 1/i as r from @t
end try
begin catch
select 'div by 0'
end catch
select * from @t2
运行此操作时,您将看到@ t2不包含任何行。
如果您希望进一步了解SQL Server在进行除零时的行为,请参阅Erland Sommarskog错误处理文档中的ARITHABORT, ARITHIGNORE and ANSI_WARNINGS。
答案 1 :(得分:1)
是。它将显示两个结果。它可以通过两种方式解决
<强> 1。使用存储过程
如果您想根据TRY
和CATCH
显示结果,请尝试使用OUT
参数返回结果
CREATE PROCEDURE ProcedureName
@RESULT VARCHAR(100) OUTPUT
AS
BEGIN
begin try
select @RESULT = 1/0
end try
begin catch
select @RESULT = 'div by 0'
end catch
select @RESULT
END
<强> 2。使用无存储过程
声明一个包含基于TRY
和CATCH
DECLARE @RESULT VARCHAR(100)
begin try
select @RESULT = 4/0
end try
begin catch
select @RESULT = 'div by 0'
end catch
select @RESULT