字符串范围比较(CompareTo)

SQL 中的字符串比较

在 SQL 中,字符串可以直接使用 >=<= 进行字典序比较:

SELECT TOP (1000000000) [t21].[nm], [t21].[bh]
FROM [dbo].[XX] AS [t21]
WHERE ([t21].[bh] >= 'FA32014001') AND ([t21].[bh] <= 'FA32016000')Code language: PHP (php)

LINQ 中的问题

LINQ to SQL 不支持对字符串直接使用 >= / <= 运算符:

// 编译报错:运算符 ">=" 无法应用于 "string" 和 "string"
where s.name >= "abc" && s.name <= "xyz"Code language: JavaScript (javascript)

解决方案:使用 CompareTo

string.CompareTo() 返回 int

  • 返回 负数:当前字符串小于参数
  • 返回 0:相等
  • 返回 正数:当前字符串大于参数
// 相等比较 → 用 Equals
var q = from s in db.Student
        where s.name.Equals("abc")
        select s;

// 范围比较 → 用 CompareTo
var q2 = from s in db.Student
         where s.name.CompareTo("abc") >= 0 
            && s.name.CompareTo("xyz") <= 0
         select s;Code language: JavaScript (javascript)

生成的 SQL

Equals → =

SELECT [t0].[id], [t0].[name], [t0].[age], [t0].[birthday], [t0].[nation], [t0].[classname]
FROM [dbo].[Student] AS [t0]
WHERE [t0].[name] = 'abc'Code language: PHP (php)

CompareTo → >= / <=

SELECT [t0].[id], [t0].[name], [t0].[age], [t0].[birthday], [t0].[nation], [t0].[classname]
FROM [dbo].[Student] AS [t0]
WHERE ([t0].[name] >= 'abc') AND ([t0].[name] <= 'xyz')Code language: PHP (php)

CompareTo 被翻译为 SQL 的 >= / <= 字符串比较,在数据库端按字典序执行。


方法语法写法

// 相等
var r = db.Student
    .Where(s => s.name.Equals("abc"))
    .ToList();

// 范围
var r2 = db.Student
    .Where(s => s.name.CompareTo("abc") >= 0 && s.name.CompareTo("xyz") <= 0)
    .ToList();Code language: JavaScript (javascript)

关键要点

场景LINQ 写法生成 SQL
相等s.name.Equals("abc")name = 'abc'
大于s.name.CompareTo("abc") > 0name > 'abc'
大于等于s.name.CompareTo("abc") >= 0name >= 'abc'
小于s.name.CompareTo("abc") < 0name < 'abc'
范围CompareTo("a") >= 0 && CompareTo("z") <= 0name >= 'a' AND name <= 'z'

注意:​ 字符串比较遵循数据库的排序规则(Collation),区分大小写与否取决于数据库设置,与 C# 的 string.Compare 默认行为可能不同。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注