如何确定排序规则是使用单词排序还是字符串排序?

时间:2015-08-25 16:21:26

标签: sql-server sorting unicode collation

https://stackoverflow.com/a/361059/14731讨论了“单词排序”和“字符串排序”之间的区别。

当SQL排序规则使用“单词排序”与“字符串排序”时,如何以编程方式进行查询?

推论:对于Unicode字符串,所有归类都使用“word sort”,对非Unicode字符串使用“string sort”吗?

SELECT * from sys.fn_HelpCollations()
WHERE name = 'SQL_Latin1_General_CP1_CI_AS'

提供了很多关于整理的细节,但请注意它没有提到“单词排序”。

2 个答案:

答案 0 :(得分:2)

让我们从Microsoft给出的这些类型的定义开始(取自CompareOptions Enumeration MSDN页面的“备注”部分):

  

.NET Framework使用三种不同的排序方式:单词排序,字符串排序和顺序排序。单词排序执行文化敏感的字符串比较。某些非字母数字字符可能会分配特殊权重。例如,连字符(“ - ”)可能具有非常小的权重,因此“coop”和“co-op”在排序列表中彼此相邻。字符串排序类似于单词排序,除了没有特殊情况。因此,所有非字母数字符号都在所有字母数字字符之前。序数排序根据字符串中每个元素的Unicode值比较字符串。

Unicode是文化敏感和加权的,XMLN - 前缀类型是Unicode,所以他们可以说Unicode类型中的数据使用“单词排序”而非非数据-Unicode类型使用“字符串排序”。序数是指BINBIN2归类,但BIN归类不是100%序数,因为它们如何处理第一个字符。

但是让我们看看SQL Server说它在做什么。运行以下命令:

DECLARE @SampleData TABLE (ANSI VARCHAR(50), UTF16 NVARCHAR(50));
INSERT INTO @SampleData (ANSI, UTF16) VALUES 
    ('a-b-c', N'a-b-c'),
    ('ac', N'ac'),
    ('aba', N'aba'),
    ('a-b', N'a-b'),
    ('ab', N'ab');

SELECT sd.ANSI AS [ANSI-Latin1_General_100_CI_AS]
FROM   @SampleData sd
ORDER BY sd.ANSI COLLATE Latin1_General_100_CI_AS ASC;

SELECT sd.UTF16 AS [UTF16-Latin1_General_100_CI_AS]
FROM   @SampleData sd
ORDER BY sd.UTF16 COLLATE Latin1_General_100_CI_AS ASC;

SELECT sd.ANSI AS [ANSI-SQL_Latin1_General_CP1_CI_AS]
FROM   @SampleData sd
ORDER BY sd.ANSI COLLATE SQL_Latin1_General_CP1_CI_AS ASC;

SELECT sd.UTF16 AS [UTF16-SQL_Latin1_General_CP1_CI_AS]
FROM   @SampleData sd
ORDER BY sd.UTF16 COLLATE SQL_Latin1_General_CP1_CI_AS ASC;

结果:

ANSI-Latin1_General_100_CI_AS
-------------------------------------
ab
a-b
aba
a-b-c
ac

UTF16-Latin1_General_100_CI_AS
-------------------------------------
ab
a-b
aba
a-b-c
ac

ANSI-SQL_Latin1_General_CP1_CI_AS
-------------------------------------
a-b
a-b-c
ab
aba
ac

UTF16-SQL_Latin1_General_CP1_CI_AS
-------------------------------------
ab
a-b
aba
a-b-c
ac

嗯。只有SQL_排序规则与VARCHAR字段组合才会显示为“字符串排序”。将SQL_归类与NVARCHAR字段组合进行“单词排序”是有意义的,它与非SQL_归类的Unicode处理相同。但除了作为SQL Server排序规则(即以SQL_开头)确定“字符串”与“字”排序之外,还有什么东西吗?让我们看一下我们可以提取的排序规则的唯一属性:

SELECT N'Latin1_General_100_CI_AS' AS [CollationName],
       COLLATIONPROPERTY('Latin1_General_100_CI_AS', 'CodePage') AS [CodePage],
       COLLATIONPROPERTY('Latin1_General_100_CI_AS', 'LCID') AS [LCID],
      COLLATIONPROPERTY('Latin1_General_100_CI_AS', 'ComparisonStyle') AS [ComparisonStyle]
UNION ALL
SELECT N'SQL_Latin1_General_CP1_CI_AS' AS [CollationName],
       COLLATIONPROPERTY('SQL_Latin1_General_CP1_CI_AS', 'CodePage'),
       COLLATIONPROPERTY('SQL_Latin1_General_CP1_CI_AS', 'LCID'),
       COLLATIONPROPERTY('SQL_Latin1_General_CP1_CI_AS', 'ComparisonStyle');

结果:

CollationName                  CodePage   LCID    ComparisonStyle
----------------------------   --------   ----    ---------------
Latin1_General_100_CI_AS       1252       1033    196609
SQL_Latin1_General_CP1_CI_AS   1252       1033    196609

所以,那里没有明显的差异。这似乎让我们留下了这个:

字符串排序在以下时间完成:

  • 整理名称以SQL_,AND
  • 开头
  • 数据(字段,变量,字符串文字)是非Unicode的(即CHAR / VARCHAR / TEXT)

有关Unicode排序的更多信息,请查看以下资源:

答案 1 :(得分:1)

  • srutzky's出色的答案表明,除SQL_整理器处理的非Unicode类型外,所有其他数据都按照“Unicode排序规则”进行排序。
  • 令人困惑的是,Microsoft不使用Unicode标准的排序规则。
  • 根据https://support.microsoft.com/en-us/kb/322112

      

    SQL Server 2000支持两种类型的排序规则:

         
        
    • SQL排序规则
    •   
    • Windows排序规则
    •   
         

    [...]

         

    对于Windows排序规则,使用与Unicode数据相同的算法来实现非Unicode数据的比较。

         

    [...]

         

    SQL排序规则用于排序非Unicode数据的规则与Microsoft Windows操作系统提供的任何排序例程不兼容;但是,Unicode数据的排序与特定版本的Windows排序规则兼容。

  • 我将此解释为:

    • SQL_整理者是“SQL排序规则”
    • 所有其他合作者都是“Windows合作者”。
    • SQL_整理器处理的非Unicode类型外,所有其他数据均按“Windows排序规则”排序。

所以,让我们深入研究“Windows排序规则”。

//  Sorting Flags.
//
//    WORD Sort:    culturally correct sort
//                  hyphen and apostrophe are special cased
//                  example: “coop” and “co-op” will sort together in a list
//
//                        co_op     <——-  underscore (symbol)
//                        coat
//                        comb
//                        coop
//                        co-op     <——-  hyphen (punctuation)
//                        cork
//                        went
//                        were
//                        we’re     <——-  apostrophe (punctuation)
//
//
//    STRING Sort:  hyphen and apostrophe will sort with all other symbols
//
//                        co-op     <——-  hyphen (punctuation)
//                        co_op     <——-  underscore (symbol)
//                        coat
//                        comb
//                        coop
//                        cork
//                        we’re     <——-  apostrophe (punctuation)
//                        went
//                        were