SQL Server 2008 R2日语错误(NVARCHAR)字符串比较?

问题描述:

问题

当我运行2008 R2,两个不同的日文Unicode字符串被视为相等SQL Server上的以下查询:SQL Server 2008 R2日语错误(NVARCHAR)字符串比较?

SELECT 
    CASE 
     WHEN N'食料' = N'食料ㇰ ㇱ ㇲ ㇳ' 
      THEN 1 
     ELSE 0 
    END; 

--result: 1 

我知道假名后的汉字是半角但由于没有类似的全角假名,所以我不会指望宽度敏感度或假名敏感度。但是,如果假名与全宽版本取代了比较的行为与预期:

SELECT 
    CASE 
     WHEN N'食料' = N'食料ク シ ス ト' 
      THEN 1 
     ELSE 0 
    END; 

--result: 0 

尝试的解决方案

这使我认为这个问题可能与我整理这是SQL_Latin1_General_CP1_CI_AS

首先,我试过Latin1_General_CI_AS以防万一它是SQL Unicode比较的怪癖,但是这并没有解决问题。

然后,我想通使用半角尾随假名时,我会用最严格的整理可能(在所有灵敏度),但其它归类,包括Latin1_General_CS_AS_KS_WSJapanese_Unicode_CS_AS_KS_WS没有改变的结果(全部正确识别与全宽度之差拖尾假名)。

要验证字符串在字节级别不同,我在删除字符串的N(nvarchar)标识并验证它返回0的预期结果后运行带有半角尾随kana的查询。

问题

这是怎么回事?我只是没有尝试正确的整理?这是SQL Server 2008 R2中的错误吗?有没有关于日本Unicode的具体内容我不知道?为什么半角尾随假名的出现不会使这些字符串不同?

PS我不知道日语,所以如果我搞砸了我对人物的描述,我很抱歉。

它的长短之处在于,在大量的排序规则中,第一个示例中的字符等于空格。

在进行字符串比较时,SQL服务器消除了字符串末尾的尾随空格(一种例外情况是当您使用LIKE时,但这里没有这样做)。

例如,在字符串N'食料ㇰ ㇱ ㇲ ㇳ'中,之后的每个字符都被视为尾部空格,并在进行字符串比较时将其删除。

要做到快速检查与给定的规则,则可以运行以下查询:

WITH 
    Vals AS (SELECT FullString, StringNum FROM (VALUES (N'食料', 1), (N'食料ㇰ ㇱ ㇲ ㇳ', 2), (N'食料ク シ ス ト', 3)) AS T(FullString, StringNum)), 
    CTE AS -- A recursive CTE to split the characters up in your strings and check the individual characters. 
    (
     SELECT FullString, 
       StringNum, 
       IndividualCharacter = SUBSTRING(FullString, 1, 1), 
       UnicodeNumber = UNICODE(SUBSTRING(FullString, 1, 1)), 
       UnicodeBinary = CAST(SUBSTRING(FullString, 1, 1) AS VARBINARY(2)), 
       CharPosition = 1 
     FROM Vals 
     UNION ALL 
     SELECT V.FullString, 
       V.StringNum, 
       IndividualCharacter = SUBSTRING(V.FullString, C.CharPosition + 1, 1), 
       UnicodeNumber = UNICODE(SUBSTRING(V.FullString, C.CharPosition + 1, 1)), 
       UnicodeBinary = CAST(SUBSTRING(V.FullString, C.CharPosition + 1, 1) AS VARBINARY(2)), 
       CharPosition = C.CharPosition + 1 
     FROM Vals AS V 
     JOIN CTE AS C 
      ON C.StringNum = V.StringNum 
     WHERE C.CharPosition + 1 <= LEN(V.FullString) 
    ) 
SELECT C.*, 
     CharacterEqualToSpace = CASE WHEN NCHAR(C.UnicodeNumber) COLLATE Japanese_Unicode_CS_AS_KS_WS = NCHAR(32) THEN 1 ELSE 0 END, 
     FullStringWithoutSpace = SUBSTRING(C.FullString, 1, (SELECT MAX(CharPosition) FROM CTE AS C2 WHERE C2.StringNum = C.StringNum AND NCHAR(C2.UnicodeNumber) COLLATE Japanese_Unicode_CS_AS_KS_WS != NCHAR(32))) -- Eliminate white space on the end for this collation, with a substring ending at the last character that does not equal white space. 
FROM CTE AS C 
ORDER BY StringNum, CharPosition; 

从做一些快速测试... - 日本的排序规则是不会治疗那些特定的字符作为一个空格:任何BIN整理,Japanese_Bushu_Kakusu,Japanese_XJIS - 日本的排序规则是治疗那些特定的字符作为一个空格:日本,Japanese90,Japanese_Unicode

注:在Japanese_Unicode_CS_AS_KS_WS中有超过21000个字符被视为空白。您可以通过针对给定整理运行如下查询来检查此问题:

WITH T(N) AS (SELECT 1 FROM (VALUES (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1)) AS A(B)), -- 16 
    T2(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1 FROM T AS A CROSS JOIN T AS B CROSS JOIN T AS C CROSS JOIN T) -- 16^4. 
SELECT WhiteSpaceCharacters = NCHAR(N) 
FROM T2 
WHERE NCHAR(N) COLLATE Japanese_Unicode_CS_AS_KS_WS = NCHAR(32);