代码之家  ›  专栏  ›  技术社区  ›  Matt Brunell

.NET和T-SQL之间的字符串比较差异?

  •  12
  • Matt Brunell  · 技术社区  · 14 年前

    在我编写的一个测试用例中,字符串比较在SQL Server/.NET clr之间的工作方式似乎不同。

    C代码:

    string lesser =  "SR2-A1-10-90";
    string greater = "SR2-A1-100-10";
    
    Debug.WriteLine(string.Compare("A","B"));
    Debug.WriteLine(string.Compare(lesser, greater));
    

    将输出:

    -1
    1
    

    此SQL Server代码:

    declare @lesser varchar(20);
    declare @greater varchar(20);
    
    set @lesser =  'SR2-A1-10-90';
    set @greater = 'SR2-A1-100-10';
    
    IF @lesser < @greater
        SELECT 'Less Than';
    ELSE
        SELECT 'Greater than';
    

    将输出:

    Less Than
    

    为什么不同?

    4 回复  |  直到 10 年前
        1
  •  10
  •   Martin Smith    14 年前

    这是 documented here .

    Windows排序规则(例如 Latin1_General_CI_AS )使用Unicode类型的排序规则。SQL排序规则没有。

    这会导致在两个字符之间对连字符进行不同的处理。

        2
  •  7
  •   KeithS    14 年前

    对于gbn的答案,您可以使用c中的compareOptions.StringSort(或使用StringComparison.Ordinal)使它们的行为相同。这将符号视为出现在字母数字符号之前,因此“—”<“0”。

    但是,Unicode和ASCII并不能解释任何问题,因为ASCII代码页的十六进制代码是逐字翻译成Unicode代码页:“-”是002D(45),而“0”是0030(48)。

    现在的情况是.NET默认使用“语言”排序,这是基于指定或当前文化对各种符号应用的非顺序排序和权重。例如,这种语言算法允许“r_)sum_”(用重音符号拼写)在排序的单词列表中紧跟“resume”(不用重音符号拼写)出现,因为“_”)在“e”之后和“f”之前被赋予一个分数顺序。它还允许将“合作”和“合作”紧密地放在一起,因为短划线符号的“权重”较低;它仅在对“位”、“位”和“位移位”(将按该顺序出现)等词进行排序时起到绝对最终的分界符的作用。

    所谓的顺序排序(严格按照Unicode值,有或没有大小写不敏感)将产生非常不同的有时不合逻辑的结果,因为在ASCII/Unicode顺序中,字母的变体通常出现在基本的未修饰拉丁字母之后,而符号出现在重新考虑。例如,“”在“z”之后,因此“resume”、“rosin”、“ruble”、“rsum”等词将按该顺序排序。位的“,”位移位“,”位的“,”位的“,”位”将按以下顺序排序:第一个是撇号,后面是破折号,然后是字母“e”,然后是字母“s”。从“自然语言”的角度来看,这两种说法都不合乎逻辑。

        3
  •  3
  •   gbn    14 年前
    • 在SQL中,您使用的varchar基本上是ascii(服从排序规则),它将给出-before 0
    • 在C中,所有字符串都是Unicode

    utf-xx(c)与ucs-2(sql-server)的细微之处相当棘手。

    编辑:

    我贴得太早了

    我在SQL Server 2008上得到“大于”,排序规则为Latin1_General_Ci_as

    编辑2:

    我也会尝试 SELECT ASCII(...) 在你的冲刺中。例如,如果SQL代码段曾经出现在Word文档中,那么(150)不是我从您的问题中复制到SQL Server以便在浏览器外进行测试的(45)。见 CP 1252 (=cp1=sql服务器lingo)

    编辑3:参见马丁·史密斯的回答:这两个排序规则有不同的排序顺序。

        4
  •  0
  •   Brandon Barkley    10 年前

    关于为什么会发生这种情况,已经有几个很好的答案了,但我确信其他人只是想知道C代码,以便按照与SQL Server相同的顺序迭代集合。我发现以下方法最有效。”序数“解决了连字符问题,而”ignorecase“似乎也反映了SQL Server的默认值。

    Debug.WriteLine(string.Compare(lesser, greater, StringComparison.OrdinalIgnoreCase));