Ech*_*lon 5 sql sql-server ado.net parameterized sql-server-2008
我有一个查询,我通过ADO.NET与SQL Server 2008R2一起使用.当我在内联使用LIKE子句时,它在不到一秒的时间内工作,从200万返回5行.如果我在SSMS查询开始时像在.NET中那样声明参数,那就需要永远.
它是相同的查询,但参数化.
第一个(工作正常)是(工作正常):
;WITH Results_CTE AS (
SELECT ld.* , ROW_NUMBER() OVER (ORDER BY PK_ID) AS RowNum
FROM list..List_Data ld
WHERE Name IS NOT NULL AND
Postcode LIKE 'SW14 1xx%'
) SELECT * FROM Results_CTE
Run Code Online (Sandbox Code Playgroud)
永远需要的第二个是:
declare @postcode varchar(10) = 'SW14 1xx'
;WITH Results_CTE AS (
SELECT ld.* , ROW_NUMBER() OVER (ORDER BY PK_ID) AS RowNum
FROM list..List_Data ld
WHERE Name IS NOT NULL AND
Postcode LIKE @postcode +'%'
) SELECT * FROM Results_CTE
Run Code Online (Sandbox Code Playgroud)
我相信这与SQL Server的内部工作有关,但我真的不知道.
小智 5
我在谷歌上搜索 C# 中 SqlCommand.Parameters.Add() 的潜在问题,并找到了此页面。我知道这是一篇 SQL Server 帖子,但其他人可能会通过 google 找到它,并且它可能会对他们使用 C# 有所帮助。
对我来说,以上答案都不起作用,所以我尝试了另一种方法。
代替:
cmd.Parameters.Add(new SqlParameter("@postcode", postcode));
Run Code Online (Sandbox Code Playgroud)
我用这个代替:
// Replace SqlDbType enumeration with whatever SQL Data Type you're using.
cmd.Parameters.Add("@postcode", SqlDbType.VarChar).Value = postcode;
Run Code Online (Sandbox Code Playgroud)
并且不要忘记名称空间:
using System.Data;
Run Code Online (Sandbox Code Playgroud)
希望这对某人有帮助!
使用
SELECT *
FROM Results_CTE
OPTION (RECOMPILE)
Run Code Online (Sandbox Code Playgroud)
SQL Server 不会嗅探变量的值,因此它不知道变量的选择性有多大,并且可能会假设查询将返回比实际情况多得多的行,并为您提供一个针对该情况优化的计划。
在你的情况下,我很确定在好的计划中你会发现它使用非覆盖非聚集索引来评估谓词PostCode和一些查找来检索丢失的列,而在坏的计划中(因为它猜测查询将返回更多的行)它避免了这种情况,有利于全表扫描。