检查SQL查询是否返回结果的有效方法

时间:2009-11-10 15:31:00

标签: sql

我想编写一个简单返回1或0的查询,具体取决于是否有结果。

我正在考虑使用这个

IF EXISTS(
      select * from myTable 
      where id=7 and rowInsertDate BETWEEN '01/01/2009' AND GETDATE()
)
SELECT 1
ELSE
SELECT 0

这是一般的前提。

最终结果实际上是一个更复杂的查询,采用一对多参数,并使用sp_executesql构建和执行字符串

我的问题是让'计数'返回376986并需要4秒钟来计算。使用IF EXISTS会在找到满足条件的1行后立即停止。

我决定使用IF EXISTS或只是查询@@ ROWCOUNT并查看它是否大于零。

我确实尝试了一些测试,并且几乎都以相同的速度运行,但是在2年的时间里,有很多数据可能使用IF EXISTS会不会有性能提升?

由于

9 个答案:

答案 0 :(得分:11)

你有id和日期的索引吗?

也许你只想要:

select top 1  1 from myTable where id=7 and rowInsertDate > '01/01/2009' 

注意:如果数据存在,则返回1,否则返回。

另一个编辑。如果没有数据,则不会返回值为null的行,而是不返回任何行。在更具象征意义上更像是无效。

答案 1 :(得分:10)

这是我在项目中获得的最快速度:

SELECT CASE WHEN EXISTS (
  select top 1 1 
  from myTable 
  where id=7 
  and rowInsertDate BETWEEN '01/01/2009' AND GETDATE()
) THEN 1 ELSE 0 END AS AnyData

答案 2 :(得分:7)

如果EXISTS应该更有效率,因为它被优化为在找到第一行后立即停止。这就是我总是会做这种检查,而不是使用COUNT()。

为了进行性能比较,只需确保通过在每次测试之前清除数据和执行计划缓存(仅限非生产数据库服务器)来公平地进行测试:

DBCC FREEPROCCACHE
DBCC DROPCLEANBUFFERS

答案 3 :(得分:3)

我会这样写:

IF EXISTS(
      SELECT 0 FROM myTable 
      WHERE id=7 and rowInsertDate BETWEEN '01/01/2009' AND GETDATE()
)
SELECT 1
ELSE
SELECT 0

这样你不会返回任何数据只是检查条件。我发现这个查询结构超级快。

答案 4 :(得分:2)

如果您不需要376986行,只想知道是否存在某些内容,那么IF EXISTS会更有意义。 另外,另一个有用的方法是请求索引列(主键)而不是*,因为您不关心实际数据。

答案 5 :(得分:1)

  

最终结果实际上是一个   更复杂的查询,拿一个   许多参数和字符串构建   使用sp_executesql

执行并执行

我认为你至少需要完整的FROM,JOIN和WHERE语法,否则你的实际查询可能会找不到(例如通过添加一个不在原始IF EXISTS查询中的INNER JOIN,结果证明不满意)。

如果您遇到这种麻烦,您可能希望将PK转换为某种“批次ID保持表”,这样您就可以参考查询的第二个“演示”部分的PK。

如果您获得376,986个结果,您打算做什么?如果您要在屏幕上向用户显示这些内容,并进行某种分页,那么将结果放在“批次ID保持表”中可能有助于此(尽管显然,对于udnerlying数据的任何添加/删除等)会破坏分页显示。)

或者,如果你打算使用分页,只需使用TOP / LIMIT / SET ROWCOUNT将结果限制为第一页完整(确保你有一个ORDER BY,这样序列是可重复的),然后整理出什么当用户按下NEXT-PAGE按钮时(我们通过包含显示的最后一条记录的PK的NEXT-PAGE按钮按顺序处理它,以便下一页可以从那时起恢复)

查询优化器会根据SELECT列表执行不同的操作 - 因此询问“IF EXISTS”后跟“SELECT Col1,COl2,... FROM ...”实际上可能意味着您运行完整的查询两次,不同的是,使用不同的缓存数据和查询计划,总体而言,这可能会对您的服务器造成更大的压力,并导致用户等待更长时间,而不仅仅是设置第一页/ 100行等。

SQL Server将缓存sp_ExecuteSQL的查询计划,但请确保参数化查询以便在可能的情况下重新启动缓存计划

答案 6 :(得分:0)

首先,您应该尝试假设一个数据库包含您认为您(或您的继任者)可能需要在两年内处理的数据。那么你的测试将会更有效率。

如果EXISTS()速度更快,因为数据库引擎只需找到符合条件的第一条匹配记录。当然,使用适当的索引会更快。

另一个提示,不要使用*,因为您实际上不需要检索列。

IF EXISTS(select 1 from myTable where id=7 and rowInsertDate BETWEEN '01/01/2009' AND GETDATE())

...应该(从我读过的内容)工作得更快。

答案 7 :(得分:0)

我认为Alex Bagnolini的回答是正确的。系统不会让我评论他的回答(新的acct)。我做的唯一修改是将第二个1更改为id。

有时减少项目部分中的列表(即列列表)允许db引擎仅命中索引,而不是表,因此更快。当然,这取决于您的数据库引擎和索引结构/大小。 (所有rowInsertDate日期应为< getDate(),因此您可以跳过该比较)

EXISTS时选择案例(   选择前1个id   来自myTable   其中id = 7   和rowInsertDate> '01 / 01 / 2009' )然后1 ELSE 0结束为AnyData

答案 8 :(得分:0)

我只想返回 select exists 而不是将其设为 int

SELECT EXISTS(SELECT 1 FROM MY_TABLE);

它会返回:

Select result, showing single row result with column exists being true

如果您需要自定义名称,则可以这样做

SELECT EXISTS(SELECT 1 FROM MY_TABLE) AS MY_CUSTOM_NAME;