我有一个动态存储过程,必须在SQL Server 2008的case语句中动态地添加where子句。
我的程序如下。-
CREATE PROCEDURE SPGETDATA
@STRNAME NVARCHAR(100),
@STRCODE NVARCHAR(100)
BEGIN
SELECT myTable.*
FROM myTable
WHERE
IsDELETED = 0
AND STRNAME LIKE CASE WHEN (RTRIM(LTRIM(@STRNAME))) <> '' THEN
'%'+ @STRNAME + '%' ELSE '%%' END
AND STRCODE LIKE CASE WHEN (RTRIM(LTRIM(@STRCODE)) <> '') THEN
'%' + @STRCODE + '%' ELSE '%%' END**
用户可以选择@stname或@strcode。但不能同时选择两者。
在这种情况下,一个类似的语句是可以的,但另一种方式总是比查询有负担,因为它总是作为
@STRNAME like '%%'
或如下所示
@STRCODE like '%%'
现在,如果我使用这种方法,编译器是否会花费一些时间来搜索像'%%',即使没有任何匹配,还是会绕过它而不花费任何费用?我也检查了执行计划,但它没有显示类似子句的内容。
因此,我必须在webApps中使用它,所以必须考虑sp的速度。而且这个表有几百万行。
两者的执行计划都是一样的。如果我在查询中使用聚类或从查询中删除它,它显示 - 聚类索引sacn 100%。
首先,如果其中任何一列是空的,那么测试
并不是一个No-Op,而是实际上相当于测试
列
col LIKE '%%'
col IS NOT NULL
不是空
的,这很可能不是想要的效果。其次,如果该列不是空的,所以它确实是一个No-Op,那么这不是一个特别好的方法,因为SQL Server 不会 优化检查。请参阅 T-SQL中的动态搜索条件 ,了解更好的方法。
不过,在你的情况下,有可能不会有太大的区别。
因为你总是在做一个带前导通配符的搜索,针对一个或其他列,并且你在做
,那么无论如何,你可能会以全表扫描结束。
SELECT *
一种情况是,你在一个或多个列上有一个较窄的索引,可以优先于扫描整个聚类索引/表。然而,即使在这种情况下,SQL Server仍然需要做书本标记查询来检索
,所以对于那个特定的查询,可以很便宜地评估剩余谓词。
*
然而,生成的计划将完全不适合其他参数的调用,所以这种尝试性的全面查询可能会给你带来参数嗅探的问题,如下图所示。
CREATE TABLE myTable id int primary key, STRNAME VARCHAR(100) NOT NULL, STRCODE VARCHAR(100) NOT NULL, IsDELETED BIT NOT NULL DEFAULT 0, Filler CHAR(7000) NULL, INSERT INTO myTable(id, STRNAME, STRCODE) SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)), ISNULL(name,type), ISNULL(name,type) FROM master..spt_values CREATE INDEX ix ON myTable(STRNAME)
首先调用名称参数(扫描次数1,逻辑读数7)。