为什么我的存储过程无论条件逻辑如何都执行所有选择?

时间:2012-03-28 16:21:34

标签: sql sql-server-2008 stored-procedures logic

我正在使用SQL Server 2008。

我有一个有趣的场景,如果主表中有数据,存储过程(由“超级用户”编写)有一个好的运行时间(大约4秒)。如果搜索值不存在,则运行时间平均为大约3分钟。由于进程的工作方式以及使用该过程的Web应用程序,在没有数据的情况下需要空结果集。

我已经测试了下面的逻辑,其值包含数据和值,但流量似乎无效;但是,当我将我的实际查询放在else语句中时,尽管我知道逻辑分支不应该执行,但似乎总是正在评估该部分。

DECLARE @spId int

SELECT @spId = td.mainId
FROM dbo.PRIMARYTABLE
WHERE td.longId = @searchVal

IF @spId < 1 OR @spId IS NULL
BEGIN
     select 'RETURN EMPTY RESULT SET' as test
END
ELSE 
BEGIN
    SELECT 'DO ACTUAL QUERY' as test
END

当我用虚拟值(例如1111)测试时,返回选择'RETURN EMPTY RESULT SET'作为测试。当我使用我知道存在的值时,将返回SELECT'DO ACTUAL QUERY'作为测试。当我用实际的重载查询替换“SELECT'DO ACTUAL QUERY'作为测试”并使用相同的不存在的虚拟值时,它仍然看起来像是达到了ELSE子句。

我在这里缺少什么?

2 个答案:

答案 0 :(得分:1)

也许你没有展示一切。在select中没有返回任何行的分配有一个反直觉的事 - 变量的值不会被清除。将其粘贴在SSMS中:

declare @searchVal as int
set @searchVal=111

DECLARE @spId int
set @spId = 2134
SELECT @spId = td.mainId
FROM (select 839 as mainId, 0 as longid) td
where td.longId = @searchVal
print @spid

@spid将是2134.这就是为什么你应该总是使用@@ rowcount进行测试,在你的情况下

IF @@rowcount = 0 or @spId < 1 or @spId is null
BEGIN
    select 'RETURN EMPTY RESULT SET' as test
END
ELSE 
BEGIN
    SELECT 'DO ACTUAL QUERY' as test
END

longId也有可能存在重复数据,从满足@searchval条件的行返回随机mainid。

除此之外,我不知道。

答案 1 :(得分:0)

谢谢大家的建议。我为缺少发布整个存储过程而道歉,但我不允许分享那些确切的代码。我开始使用的代码段是伪代码(嗯,重命名了表和字段的实际代码)。

我认为NikolaMarkovinović可能会回答他的回答和文章链接。这整个考验都令人发狂。我用谷歌搜索,调试,然后再做一遍,然后搜索堆栈溢出。在你的建议稍作修改之后,程序神奇地开始响应我认为应该的运行时间。我不认为一些初始更改或者可能没有被sql server正确缓存;除了猜测,我什么都没有。

这是非常奇怪的,因为在一个小时或更长的时间里,它一直在运行,好像从未改变过(性能明智)......然后它就开始了。我想知道这不是我的错,也许我没有改变那个关于升级的那个,就像我在测试中做的那个......这似乎是最可行的解释。

无论如何,谢谢你的建议。我学到了一些东西,所以总是很好。