【问题标题】:SQL Server 2008 and Unicode Character comparisonSQL Server 2008 和 Unicode 字符比较
【发布时间】:2014-12-23 13:35:02
【问题描述】:

在比较两个字符串时,SQL Server 2008 似乎删除了一些 unicode 字符。考虑下表:

CREATE TABLE [dbo].[Test](
[text] [nvarchar](50) NOT NULL,
  CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED 
  (
    [text] ASC
  ))

现在如果我插入一些带有 unicode 字符的行:

insert into Test values(N'it᧠')
insert into Test values(N'it')

我得到一个唯一约束异常,即使值不同。我在这里使用默认的数据库排序规则,即 SQL_Latin1_General_CP1_CI_AS。

Violation of PRIMARY KEY constraint 'PK_Test'. Cannot insert duplicate key in object 'dbo.Test'.

请注意,并非所有 unicode 字符都会发生这种情况,而仅适用于某些字符,但我无法确定哪些 unicode 范围确实存在问题。例如,dingbat 0x2757 (❗) 被删除,但 0x2764 (♥) 没有。我想这与 0x2757 来自较新的 unicode 标准有关。

所以问题是,有什么方法可以让 SQL Server 2008 使用这些字符,或者,我可以通过编程方式检测它们(在 C# 中,通过 unicode 范围等)并预先删除它们吗?

【问题讨论】:

  • 您应该将字段类型设置为nvarchar
  • @Bayeni,并没有真正的帮助。我正在使用 nvarchar 和 N 前缀。 unicode 值正确显示在表中,问题在于比较。
  • 我不能 100% 确定为什么不比较某些字符,或者如何识别这些字符,但是您可以使用二进制排序规则来解决这个问题,例如以下工作正常 - CREATE TABLE #T (A NVARCHAR(50) COLLATE Latin1_General_BIN PRIMARY KEY); INSERT #T (A) VALUES (N'it᧠'); INSERT #T (A) VALUES (N'it');
  • @GarethD,谢谢,这是一个有趣的想法。使用二进制排序规则时我应该注意什么缺点?我没有区分大小写的问题,该字段只有小写值。

标签: c# sql-server sql-server-2008 unicode


【解决方案1】:

好吧,再深入研究一下,这几乎可以肯定是由于更新的字符,因为这也适用于 sql server 2008 等价的拉丁排序规则,但不适用于旧版本,即适用于 Latin1_General_100_CI_AS,但不适用于Latin1_General_CI_AS。要获得正确比较我使用的这些字符串的排序规则的完整列表:

IF OBJECT_ID('Tempdb..#T') IS NOT NULL
    DROP TABLE #T;
IF OBJECT_ID('Tempdb..#V') IS NOT NULL
    DROP TABLE #V;

CREATE TABLE #V (A NVARCHAR(50), B NVARCHAR(50));
INSERT #V (A, B) VALUES (N'it᧠', N'it');

CREATE TABLE #T (Collation VARCHAR(500), Match BIT);

DECLARE @SQL NVARCHAR(MAX) = (SELECT N'INSERT #T (Collation, Match) 
                                        SELECT ''' + Name + ''', CASE WHEN A = B COLLATE ' + name + ' THEN 1 ELSE 0 END
                                        FROM    #V;'
                                FROM sys.fn_helpcollations()
                                FOR XML PATH(''), TYPE
                            ).value('.', 'NVARCHAR(MAX)');

EXECUTE sp_executesql @SQL;

SELECT  *
FROM    #T
WHERE   Match = 0;

【讨论】:

    猜你喜欢
    • 2011-05-18
    • 2012-09-12
    • 1970-01-01
    • 2011-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-19
    • 2018-04-07
    相关资源
    最近更新 更多