如果select中的变量赋值返回多个值,是否可能引发错误?

时间:2010-12-31 08:55:17

标签: sql tsql sql-server-2008

我刚刚在我的一个软件上发现了一个错误,我忘记了where子句。代码是这样的:

declare @foo bigint
declare @bar bigint
select @foo = foo, @bar=bar from tbFooBar
where (....a long list of condition goes there)
     (... and an extra condition should have went there but I forgot it)

不幸的是,我忘记的where子句在非常特殊的极端情况下非常有用,并且代码已成功通过测试。

最终,查询返回了两个值而不是一个,并且生成的错误是一个要追踪的噩梦(因为它很难重现,而且这个特定的存储过程导致问题根本不明显我们发现了)

如果@ foo = foo引发异常而不是默默地从多行中分配第一个值,那么调试会容易得多。

为什么这样?我不能想到一个人实际上想要这样做而不会引起错误的情况(记住条款'不同'和'顶'是有原因的)

如果出现这种情况,有没有办法让sql server 2008引发错误?

4 个答案:

答案 0 :(得分:8)

试试这个:

declare @d datetime
select @d = arrived from attendance;
if @@ROWCOUNT > 1 begin
    RAISERROR('Was more than expected 1 row.', 16, 1)
end

答案 1 :(得分:2)

为什么这样?根据每行上分配变量 的事实,人们可以做很多事情。例如,有些人用它来执行string concatenation

@bernd_k演示了一种导致错误的方法,假设您只分配给单个变量。目前,如果您需要分配多个变量,则无法概括该技术 - 您仍需确保查询仅返回一行


如果您担心特定查询很大/很复杂/可能稍后编辑,并且有人可能会意外导致它返回其他行,您可以引入一个新变量,并使您的选择外观像这样开始:

declare @dummy bit
select @dummy = CASE WHEN @dummy is null then 1 ELSE 10/0 END

如果返回多行,则会导致错误。

答案 2 :(得分:1)

当有多个结果时,您可以像这样制定查询而不是出错:

declare @foo bigint
select @foo = (
    Select foo 
    from tbFoo
    where (....a long list of condition goes there)
         (... and an extra condition should have went there but I forgot it)
)

另一种语法的目的不是抛出错误。

修改

当您需要多于一列时,可以使用表变量,将结果分配给它并检查其行数并相应地工作。

答案 3 :(得分:0)

我会将值分配给表变量,并在分配后检查表是否有多个记录。事实上,我几乎从不依赖查询来返回一条记录,因为这是短视的。它可能在测试中,但一旦真实数据到达那里,它们通常不会,甚至可能不会。如果你考虑集合而不是一个记录,你将拥有更可靠的代码。