我有这个问题:
select '[' + p.Firstname + ']' from Person p
where p.Firstname = 'Johanne'
在表格中,我有多个具有此名字的人物,有些人在该值上有一个尾随空格(值插入错误,将予以纠正)。
为什么这个查询会给我带来这个结果(我插入括号来显示空格):
[Johanne]
[Johanne ]
[Johanne ]
[Johanne]
这是配置吗?真正的查询来自实体框架6,但是这个例子也是如此。我该如何预防?
谢谢!
编辑:我可以使用EF6和System.Data.Entity.SqlServer.SqlFunctions.DataLength
方法使其工作:
ctx.Person.FirstOrDefault(p => p.FirstName == "Johanne" && SqlFunctions.DataLength(p.FirstName) == "Johanne".Length);
答案 0 :(得分:3)
SQL Server遵循ANSI / ISO SQL-92规范(第8.2节,一般规则#3),介绍如何将字符串与空格进行比较。 ANSI标准要求对比较中使用的字符串进行填充,以便在比较它们之前使它们的长度匹配。填充直接影响WHERE和HAVING子句谓词以及其他Transact-SQL字符串比较的语义。例如,Transact-SQL认为字符串'abc'和'abc'在大多数比较操作中都是等效的。
此规则的唯一例外是LIKE谓词。当LIKE谓词表达式的右侧具有带尾随空格的值时,SQL Server不会在比较发生之前将这两个值填充到相同的长度。因为根据定义,LIKE谓词的目的是促进模式搜索而不是简单的字符串相等性测试,这不违反前面提到的ANSI SQL-92规范的部分。
答案 1 :(得分:2)
我不确定EF,但在TSQL中我使用DataLength
DataLength将返回包括尾随空白的长度 Len将返回不包括尾随空格的长度
and DataLength(p.Firstname) = Len('Johanne')
答案 2 :(得分:2)
您可以在Sql中创建一个新视图,并将该视图映射回EF对象。视图可以包含字段的长度,在使用DataLength的select中,您知道要匹配,然后您可以在使用EF时在where子句中对其进行过滤。 或者,您可以创建一个Sql Stored Proc,使用LIKE进行比较而不使用通配符(产生所需的结果)并将其映射回您的代码并在EF中的Where语句中调用它。
使用视图
Create View MyCustomView
AS
SELECT [column1,column2,etc], DATALENGTH(FirstName) AS FirstNameLength
FROM Person
GO
然后你的EF将是:
Persons.Where(p => p.FirstNameLength == "Johanne".Length && p.FirstName == "Johanne");
使用存储过程
CREATE PROCEDURE [dbo].[GetPersons]
firstName int = null
AS
BEGIN
SET NOCOUNT ON;
select [your fields here]
from persons
where FirstName like @firstName
END
在C#中确保您的映射正确,然后
this.Database.SqlQuery<Person>("GetPersons","Johanne");
EF6还支持在执行之前直接编辑DbContext中的sql。您可以开发一些自定义代码,在特定情况下替换=,但在您执行此操作之前可能更容易尝试上述内容。