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_WS
和Japanese_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);