为什么除零仍会产生结果集?

时间:2015-02-15 06:53:41

标签: sql-server tsql

我正在使用sql server 2012

这是我的疑问:

begin try 
select 1/0 
end try
begin catch
select 'div by 0'
end catch

它返回2个不同的结果:

enter image description here

但预期的结果是div by 0?因为尝试失败后的控制转移到了捕获?

那为什么会返回2个结果?

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。使用存储过程

如果您想根据TRYCATCH显示结果,请尝试使用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。使用无存储过程

声明一个包含基于TRYCATCH

的结果的变量
DECLARE @RESULT VARCHAR(100)

begin try 
  select @RESULT = 4/0           
end try
begin catch
 select @RESULT = 'div by 0'         
end catch

select @RESULT