由Entity Framework生成的SQL用于字符串匹配

时间:2009-01-29 12:06:57

标签: sql entity-framework

给定针对EF数据上下文的linq查询:

var customers = data.Customers.Where(c => c.EmailDomain.StartsWith(term))

你希望它能像这样产生SQL,对吗?

SELECT {cols} FROM Customers WHERE EmailDomain LIKE @term+’%’
实际上,它确实是这样的:

SELECT {cols} FROM Customer WHERE ((CAST(CHARINDEX(@term, EmailDomain) AS int)) = 1)

你知道为什么吗?

此外,将Where选择器替换为:

c => c.EmailDomain.Substring(0, term.Length) == term

它的运行速度提高了10倍,但仍会产生一些非常令人讨厌的SQL。

注意: Linq to SQL正确地将StartsWith转换为Like {term}%,并且nHibernate具有专用的LikeExpression。

5 个答案:

答案 0 :(得分:3)

我不知道MS SQL服务器但是在SQL服务器上紧凑LIKE'foo%'比CHARINDEX快数千倍,如果你在seach列上有INDEX。而现在我正坐着把我的头发拉出来,如何强行使用它。

http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/1b835b94-7259-4284-a2a6-3d5ebda76e4b

答案 1 :(得分:2)

原因是,与LIKE相比,CharIndex比SQL更快,更清晰。原因是, 可以 有一些疯狂的“LIKE”条款。例如:

SELECT * FROM Customer WHERE EmailDomain LIKE 'abc%de%sss%'

但是,“CHARINDEX”函数(基本上是“IndexOf”)只处理查找一组字符的第一个实例......不允许使用通配符。

所以,你的答案是:)

编辑:我只是想补充一点,我鼓励人们在他们的SQL查询中使用CHARINDEX来处理他们不需要“LIKE”的事情。需要注意的是,在SQL Server 2000中,“文本”字段可以使用 LIKE 方法,但不能使用CHARINDEX。

答案 2 :(得分:0)

LIKE和CHARINDEX之间的性能似乎差不多,所以这不应该是原因。有关讨论,请参阅herehere。此外,CAST非常奇怪,因为CHARINDEX返回一个int。

答案 3 :(得分:0)

charindex返回第二个词中第一个词的位置。

sql以1开头作为第一个位置(0 =未找到)

http://msdn.microsoft.com/en-us/library/ms186323.aspx

我不知道为什么它会使用该语法,但这就是它的工作原理

答案 4 :(得分:0)

我同意它并不快,我正在从我们的数据库中检索成千上万的行,并以字母i命名。但我确实发现你需要使用>而不是= ...所以使用

{cols} FROM Customer WHERE ((CAST(CHARINDEX(@term, EmailDomain) AS int)) > 0)

而不是

{cols} FROM Customer WHERE ((CAST(CHARINDEX(@term, EmailDomain) AS int)) = 1)

这是我的两个测试......

select * from members where surname like '%i%'    --12 seconds

select * from sc4_persons where ((CAST(CHARINDEX('i', surname) AS int)) > 0)  --12 seconds

select * from sc4_persons where ((CAST(CHARINDEX('i', surname) AS int)) = 1)  --too few results