Sql server SQL Server 2008 R2日语(NVARCHAR)字符串比较出错? 问题
在SQL Server 2008 R2上运行以下查询时,两个不同的日文unicode字符串被视为相等:Sql server SQL Server 2008 R2日语(NVARCHAR)字符串比较出错? 问题,sql-server,unicode,sql-server-2008-r2,Sql Server,Unicode,Sql Server 2008 R2,在SQL Server 2008 R2上运行以下查询时,两个不同的日文unicode字符串被视为相等: SELECT CASE WHEN N'食料' = N'食料ㇰ ㇱ ㇲ ㇳ' THEN 1 ELSE 0 END; --result: 1 我知道汉字后面的假名是半宽的,但由于没有类似的全宽假名,我不认为宽度敏感或假名敏感有什么关系。但是,如果将假名替换为全宽版本,则比较的行为与预期相同: SELECT CASE
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\u Latin1\u General\u CP1\u CI\u AS
首先,我尝试了Latin1\u General\u CI\u AS
,以防这是SQL Unicode比较的一个怪癖,但这并没有解决问题
然后,我想我会使用尽可能严格的排序规则(所有敏感度都是),但其他排序规则,包括Latin1\u General\u CS\u AS\u KS\u WS
和Japanese\u Unicode\u CS\u AS\u KS\u WS
在使用半宽尾随假名时并没有改变结果(都正确地识别了与全宽尾随假名的差异)
为了验证字符串在字节级别上是否不同,我在删除字符串的N
(nvarchar)指定后使用半宽度尾随假名运行了查询,并验证了它是否返回了0
的预期结果
问题
这是怎么回事?我只是没有尝试正确的排序吗?这是SQL Server 2008 R2中的错误吗?关于日文Unicode有什么我不知道的地方吗?为什么半宽度尾随假名的存在不会使这些字符串有所不同
PS我不懂日语,所以如果我把我对字符的描述弄错了,我道歉。长短不一的是,在大量排序中,第一个示例中的字符等于一个空格 在进行字符串比较时,SQL server会消除字符串末尾的尾随空格(一个例外是使用类似于的
时,但在这里不这样做)
例如,在字符串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;
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);