Unicode字符导致SQL Server 2005字符串比较中出现问题

时间:2010-02-16 19:43:18

标签: sql-server unicode collation string-comparison

此查询:

select *
from op.tag
where tag = 'fussball'

返回标记列值为“fußball”的结果。列“tag”定义为nvarchar(150)。

虽然我知道他们是similar words grammatically,但有人可以解释和捍卫这种行为吗?我假设它与相同的排序规则设置相关,允许您更改列/表的区分大小写,但谁会想要这种行为?由于违反约束,当另一个值存在时,列上的唯一约束也会导致插入一个值失败。我该怎么关掉它?

后续奖励积分问题。解释为什么此查询不返回任何行:

select 1 
where 'fußball' = 'fussball'

奖金问题(回答?):@ScottCher私下向我指出,这是因为字符串文字“fussball”被视为varchar。此查询返回结果:

select 1 
where 'fußball' = cast('fussball' as nvarchar)

但话说回来,这个没有:

select 1 
where cast('fußball' as varchar) = cast('fussball' as varchar)

我很困惑。

5 个答案:

答案 0 :(得分:3)

我猜你的连接/表/数据库的Unicode排序规则集指定了ss ==ß。后一种行为是因为它是在错误的快速路径上,或者它可能是二进制比较,或者你可能没有以正确的编码传递ß(我同意它是愚蠢的)。

http://unicode.org/reports/tr10/#Searching提到U + 00DF是特殊的。这是一篇富有洞察力的摘录:

  

语言敏感的搜索和   匹配与...密切相关   排序规则。字符串比较为   在某种程度上等于那些   在做的时候应该匹配   语言敏感的匹配。对于   例如,在主要力量,“ß”   将与“ss”相匹配   UCA和“aa”匹配“å”   丹麦剪裁UCA。

答案 1 :(得分:1)

SELECT 返回一行,其中包含排序规则Latin1_General_CI_AS(SQL2000)。

使用排序规则Latin1_General_BIN

您可以使用COLLATE<分配表格列进行整理。整理> N / VARCHAR之后的关键字。

您还可以使用语法

比较具有特定归类的字符串
string1 = string2 COLLATE < collation >

答案 2 :(得分:1)

一些帮助者答案 - 不是你问题的完整答案,但仍然可能有帮助:

如果您尝试:

SELECT 1 WHERE N'fußball' = N'fussball'  

你会得到“1” - 当使用“N”来表示Unicode时,这两个字符串被认为是相同的 - 为什么会这样,我还不知道(还)。

要查找服务器的默认排序规则,请使用

SELECT SERVERPROPERTY('Collation')

要在数据库中查找给定列的排序规则,请使用以下查询:

SELECT
  name 'Column Name', 
  OBJECT_NAME(object_id) 'Table Name', 
  collation_name
FROM sys.columns
WHERE object_ID = object_ID('your-table-name') 
AND name = 'your-column-name'

答案 3 :(得分:1)

这不是解释行为的答案,但可能是相关的:

this问题中,我了解到使用

的整理
Latin1_General_Bin 

将避免大多数校对怪癖。

答案 4 :(得分:1)

  

奖金问题(回答?):@ScottCher   私下向我指出这一点   是由于字符串文字   “fussball”被视为varchar。   此查询返回结果:

     

select 1 where 'fußball' =   cast('fussball' as nvarchar)

在这里,您正在处理SQL Server数据类型优先级规则,如Data Type Precedence中所述。始终使用较高优先级类型进行比较:

  

当操作员组合两个时   不同数据类型的表达式,   数据类型优先级的规则   用数据类型指定   较低的优先级转换为   优先级较高的数据类型。

由于nvarchar的优先级高于varchar,因此您的示例中的比较将采用nvarchar类型,因此它与select 1 where N'fußball' =N'fussball'完全相同(即使用Unicode类型)。我希望这也能说清楚为什么你的最后一个案例不会返回任何一行。