【问题标题】:Unicode normalization in SQL Server 2008 R2SQL Server 2008 R2 中的 Unicode 规范化
【发布时间】:2015-02-21 19:11:55
【问题描述】:

@我在表格中有一行,其中包含以下文本“Urbański,Mariusz”。字符“ń”的十六进制表示是“6e cc 81”。所以这是以分解的 Unicode 规范化形式存储的。

当我使用如下查询“...... where Identification = N'Urbański, Mariusz'”和字符“ń”匹配分解形式(“6e cc 81”)时,查询返回预期的记录。

如果我使用合成 Unicode 规范化表单 ("ń" = "c5 84") 运行完全相同的查询,我不会得到任何结果。

我还尝试了“Select 1 Where N'Urbański, Mariusz' = N'Urbański, Mariusz'”,其中我使用了“ń”的 2 个变体,它们总是返回 true。

有没有办法让 SQL Server 将这两个值视为相等?

这是 Rhys Jones 要求的我的数据库配置

Database Collation : "Danish_Norwegian_CI_AS"
Column1 : IdRightsHolderSourceIdentification = NULL  
Column2 : VersionInfo = NULL  
Column3 : Source = "Danish_Norwegian_CI_AS"
Column4 : Identification = "SQL_Latin1_General_CP437_BIN"
Column5 : RightsHolder = NULL

正如 Rhys Jones 猜测的那样,有问题的列是 column4,它有一个二进制排序规则(这就是 BIN 的最终含义,对吗?)。非常感谢您的帮助。

【问题讨论】:

  • 请您多解释一下您是如何使用的字符“ń”的十六进制表示是“6e cc 81”。
  • @BI 老兄,我相信他指的是stackoverflow.com/questions/6639770/…
  • @BIDude 这些十六进制代码是 UTF-8。用小写字母编写的 unicode 通常表示任何编码,(OTOH 全部大写,通常是 MSWIN 使用的 UTF-16(小端序)。)

标签: sql-server unicode sql-server-2008-r2 normalization unicode-normalization


【解决方案1】:

我可以从您的问题中看出您了解 Unicode,所以我猜您缺少的一点是在 SQL Server 中有一种称为排序规则的东西。这决定了 SQL Server 如何比较值。我已经编写了一个脚本来演示两种名称形式之间的各种成功和不成功的比较。我当前使用的 SQL Server 设置使用 Latin1_General_CI_AS,在该名称下,两种形式的名称都是相等的。我已经尝试了一些东西,但除非我使用二进制排序规则,否则我不能让它们不相等。我有兴趣了解您的服务器和数据库排序规则,并查看您的表的表定义(包括排序规则)。

希望对你有帮助,

里斯

-- UTF8 character list -- http://www.fileformat.info/info/charset/UTF-8/list.htm?
--    n - LATIN SMALL LETTER N (U+006E) 6e 
--    ́    - COMBINING ACUTE ACCENT (U+0301) cc81 
--    ń - LATIN SMALL LETTER N WITH ACUTE (U+0144) c584 

create table dbo.MyTable (id int not null, name nvarchar(100) collate Latin1_General_CI_AS not null)

declare @a nvarchar(100); set @a = N'Urba' + nchar(0x0144) + N'ski, Mariusz'
declare @b nvarchar(100); set @b = N'Urba' + nchar(0x6e) + nchar(0x0301) + N'ski, Mariusz'

insert dbo.MyTable values (1, @a)
insert dbo.MyTable values (2, @b)

-- Display server, database and column collations
select
    SERVERPROPERTY(N'Collation') as [server_collation],
    DATABASEPROPERTYEX(DB_NAME(), N'Collation') as [database_default_collation],
    c.collation_name as [column_collation]
from
    sys.objects t join sys.columns c on c.object_id = t.object_id
where 
    t.object_id = object_id('dbo.MyTable') and c.name = 'name'

-- Test with Latin1_General_CI_AS
select id, name from dbo.MyTable where name collate Latin1_General_CI_AS = @a collate Latin1_General_CI_AS

-- Test with French_CI_AS
select id, name from dbo.MyTable where name collate French_CI_AS = @a collate French_CI_AS

-- Test with Latin1_General_BIN2
select id, name from dbo.MyTable where name collate Latin1_General_BIN2 = @a collate Latin1_General_BIN2

【讨论】:

  • @AlexanderKentros - 如果您编辑原始问题,您可以更有效地添加此信息。使用格式帮助查看如何布局文本。
  • 我需要试试这个,但我认为这是问题所在。非常感谢。
  • 我已经证实这确实是我面临的问题。很好的解释。谢谢
猜你喜欢
  • 2011-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-20
相关资源
最近更新 更多