【问题标题】:Why 'Weiss'='Weiß' or search in SQL Server over Unicode column为什么 'Weiss'='Weiß' 或在 SQL Server 中搜索 Unicode 列
【发布时间】:2015-05-16 17:28:04
【问题描述】:

我在 SQL Server 中将列定义为 nvarchar,因此(我认为)'Weiss'=='Weiß'。但在我的 c# 代码中,'Weiss'!='Weiß'

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[Tags]
(
    [Id] [bigint] IDENTITY(1,1) NOT NULL,
    [Value] [nvarchar](125) NOT NULL,
    [IsBlocked] [bit] NOT NULL,
    [Created] [datetimeoffset](7) NOT NULL,
    [Updated] [datetimeoffset](7) NOT NULL,

    CONSTRAINT [PK_dbo.Tags] 
    PRIMARY KEY CLUSTERED ([Id] ASC)
        WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
              IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
              ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

在 SQL Server 中:

SELECT *
FROM [Tags]
WHERE Value = 'Weiss Kreuz'

返回值为 'Weiß Kreuz' 的行

有人能解释一下这是怎么发生的,以及如何在 c# 和 SQL Server 中进行相同的比较吗?

【问题讨论】:

  • 你试过不区分大小写的等号吗?
  • 在 sql 或 c# 中?不,不知何故 sql 'ss' 等于 'ß'
  • 在 C# 中。 SQL 通常配置为进行不区分大小写的字符串比较,而 C# 通常配置区分大小写的比较。

标签: c# sql-server unicode


【解决方案1】:

这完全取决于排序规则和比较的完成方式:

string str1 = "Weiss";
string str2 = "Weiß";
bool res = string.Compare(str1, str2) == 0;
bool res2 = string.Equals(str1,str2,StringComparison.CurrentCulture);

如果两个字符串相等,string.Compare 将返回 0

来自string.Comparemsdn:

比较使用当前文化来获取特定于文化的信息,例如大小写规则和单个字符的字母顺序

string.Equals(string, string)

此方法执行顺序(区分大小写和不区分区域性)比较。

string.Equals(string, string, StringComparison)

comparisonType 参数指示比较是否应该使用当前或不变的文化,尊重或忽略被比较的两个字符串的大小写,或者使用单词或序数排序规则。

如果您环顾四周(例如SQL query that distinguishes between ß and ss),您会发现在许多 sql 排序规则中都知道ss == ß

一般情况你不应该重新排序由 SQL 排序的客户端事物,也不应该重新比较由 SQL 比较的客户端事物,因为 SQL 的排序规则和 .NET 的排序规则是不同的对于小事(通常是因为他们使用不同版本的 Unicode,或者因为出于兼容性原因他们做事不同)

【讨论】:

    【解决方案2】:

    您可能知道在某些词中使用the German letter eszett (ß) 代替德语中的双s。因此,如果您对 WeissWeiß(意思是 White)这两个词进行 UNICODE 比较,它们被认为是相同的。

    在 C# 中,您可以使用 String.Compare 进行 UNICODE 比较(也称为文化敏感比较):

    String.Compare("Weiss", "Weiß")
    

    这将返回 0 表示两个字符串相等。

    使用等于运算符:

    "Weiss" == "Weiß"
    

    返回 false,但此运算符使用不区分文化的比较。

    SQL Server handles sorting and comparison of strings using a collation。 SQL Server 的早期版本使用的规则与 Windows(以及 .NET/C#)使用的规则不同,但现在 SQL Server 排序规则已与 Windows 中的 UNICODE 规则保持一致。

    这提供了 SQL Server 中数据类型之间的一致性,并且还允许开发人员使用 SQL Server 使用的相同规则在其应用程序中对字符串进行排序。

    【讨论】:

    • 在 C# 中,StringComparison.CurrentCulture(对于我知道的所有文化)和StringComparison.InvariantCulture 这两个值被认为是相同的,而对于StringComparison.Ordinal,它们显然是不同的。 CompareCompreTo 的默认设置是使用当前区域性。 ==Equals 的默认值是使用序数比较。同样,此评论仅针对 C#。
    • @JeppeStigNielsen 您所做的评论不是针对 C#,而是针对 .NET,因为 .NET 库就是这样完成的。如果您希望 Jeppe# 语言以不同的方式执行此操作,则需要您的 Jeppe# 编译器来捕获对 string== 和 string.Equal 方法的所有调用并将它们重定向到其他一些方法。
    • @xanatos 正确。谢谢你说清楚!唯一特定于 C# 的是运算符 bool operator ==(string x, string y),它在技术上不是 CLI 方法。我提到的其他所有内容都是关于 .NET 库的。
    • @Jeppe 比这还要大...甚至operator== 也是.NET 的一部分...查看IL 代码:goo.gl/cJTJfGcall bool [mscorlib]System.String::op_Equality(string, string)
    • @xanatos 哦,我也错了。你是对的,当然还有that method is documented。我想我将它与重载 bool operator ==(object x, object y) 混淆了,这不是 System.Object 或其他地方的真正方法。但这种超载当然与这里无关。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-29
    • 2013-08-05
    • 2021-10-13
    • 2014-09-04
    • 2018-02-12
    • 2011-04-15
    • 1970-01-01
    相关资源
    最近更新 更多