在“存在”函数中具有cte和top 1的标量值函数

时间:2016-05-11 13:38:28

标签: sql-server exists scalar-subquery

我的查询使用'exists'函数作为过滤器,它内部有标量值函数。标量值的函数包含cte和“(select top 1 1)”。当我使用存在时,它根本不会过滤。相反,当我使用“where 1 =(svf)”时,似乎工作。我想念存在查询中的任何内容或任何错误吗?


SELECT * FROM TBL1
WHERE EXISTS (SELECT SVF(1,2))
--where SVF is my scalar valued from which returns bit and looks like as shown below.

CREATE FUNCTION SVF ( @x int, @y int ) RETURNS bit AS BEGIN declare @result bit ;WITH T1 AS ( SELECT * from tbl2 ) SELECT @result= (select top 1 1 FROM t1 ) return isnull(@result,0) END GO

--the following query works SELECT * FROM TBL1 WHERE 1=(SELECT SVF(1,2))

2 个答案:

答案 0 :(得分:2)

EXISTS()运算符

  

如果子查询包含任何行,则返回TRUE。

强调添加

这很重要,因为你的Scalar函数将返回一个值,1或0(正如Damien所指出的,即使NULL也会满足)但是它将返回一个值

因为它返回一个值,EXISTS总是返回TRUE。

您基本上是在询问SQL Server:

-- Doesn't matter what my function returns as it's always going to return a row...
BEGIN 
-- then run this query
SELECT * FROM TBL1;
END;

尝试重新编写查询以不使用该函数,因为标量函数通常不是基于设置的,因此通常是性能杀手。

答案 1 :(得分:1)

正如已经说过的那样,exists函数将始终评估为true,因为标量函数返回一个值。存在仅在函数调用最终不返回值时才起作用。

您可以使用交叉申请,例如:

SELECT * 
FROM TBL1 as T1
CROSS APPLY (SELECT svf = dbo.SVF(T1.x,T2.y)) c
WHERE svf = 1

编辑: 请记住,标量函数在大多数情况下是性能杀手,因为它们不是可以攻击的。