C# 为什么';韦斯'=';魏ß';或通过Unicode列在SQL Server中搜索

C# 为什么';韦斯'=';魏ß';或通过Unicode列在SQL Server中搜索,c#,sql-server,unicode,C#,Sql Server,Unicode,我在SQL Server中将列定义为nvarchar,因此(我认为)'Weiss'='Weiß'。但在我的c#code'Weiss'!='韦氏 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] [bi

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

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中进行相同的比较吗?

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

string str1 = "Weiss";
string str2 = "Weiß";
bool res = string.Compare(str1, str2) == 0;
bool res2 = string.Equals(str1,str2,StringComparison.CurrentCulture);
其中
string.Compare
如果两个字符串相等,则返回
0

从msdn:

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

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

comparisonType参数指示比较是否应使用当前区域性或不变区域性、尊重或忽略正在比较的两个字符串的大小写,或使用word或ordinal排序规则

如果您环顾四周(例如),您将看到,在许多sql排序规则中,
ss==ß


一般来说您不应该重新排序按SQL排序的客户端内容,也不应该重新比较按SQL排序的客户端内容,因为SQL的排序规则和.NET的排序规则对于小型内容是不同的(通常是因为他们使用不同版本的Unicode,或者出于兼容性原因,他们的做法不同)

这一切都取决于排序规则和比较方式:

string str1 = "Weiss";
string str2 = "Weiß";
bool res = string.Compare(str1, str2) == 0;
bool res2 = string.Equals(str1,str2,StringComparison.CurrentCulture);
其中
string.Compare
如果两个字符串相等,则返回
0

从msdn:

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

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

comparisonType参数指示比较是否应使用当前区域性或不变区域性、尊重或忽略正在比较的两个字符串的大小写,或使用word或ordinal排序规则

如果您环顾四周(例如),您将看到,在许多sql排序规则中,
ss==ß

一般来说您不应该重新排序按SQL排序的客户端内容,也不应该重新比较按SQL排序的客户端内容,因为SQL的排序规则和.NET的排序规则对于小型内容是不同的(通常是因为他们使用不同版本的Unicode,或者出于兼容性原因,他们的做法不同)

正如你可能知道的,在某些单词中,在德语中使用双s而不是双s。因此,如果你对单词Weiss和Weiß(意思是白色)进行Unicode比较,他们被认为是相同的

在C#中,您可以使用以下方法进行UNICODE比较(也称为区域性敏感比较):

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

使用equals运算符:

"Weiss" == "Weiß"
返回false,但此运算符使用不区分区域性的比较

。早期版本的SQL Server使用的规则与Windows(以及.NET/C#)使用的规则不同,但现在SQL Server排序规则已与Windows中的UNICODE规则对齐

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

正如你可能知道的那样,在德语中,有些单词使用的是双s而不是双s。因此,如果你对单词Weiss和Weiß(意思是白色)进行UNICODE比较,它们被认为是相同的

在C#中,您可以使用以下方法进行UNICODE比较(也称为区域性敏感比较):

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

使用equals运算符:

"Weiss" == "Weiß"
返回false,但此运算符使用不区分区域性的比较

。早期版本的SQL Server使用的规则与Windows(以及.NET/C#)使用的规则不同,但现在SQL Server排序规则已与Windows中的UNICODE规则对齐

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


您是否在sql或c#中尝试过不区分大小写的equals?否。不知何故,sql“ss”在c#中等于“ß”。sql通常被配置为进行不区分大小写的字符串比较,而c#通常是区分大小写的比较。您是否在sql或c#中尝试过不区分大小写的equals?否。不知何故,sql“ss”在c#中等于“ß”。sql通常被配置为进行case不区分大小写的字符串比较,而C#通常区分大小写。在C#中,使用
StringComparison.CurrentCulture
(适用于我知道的所有区域性)和
StringComparison.InvariantCulture
这两个值被认为是相同的,而
StringComparison.Ordinal
则明显不同。
Compare
CompreTo
的默认值是使用当前区域性。
==
Equals
的默认值是使用顺序比较。同样,这条评论是关于C#的。@JeppeStigNielsen你的评论不是针对C#的,而是针对.NET的,因为.NET库就是这样做的。如果你想让Jeppe#语言做得不同,你需要你的Jeppe#编译器捕获对string==和string.Equal方法的所有调用,并将它们重定向到其他方法。@xanatos正确。谢谢你说得很清楚!C#唯一特定的东西是操作符
bool操作符==(字符串x,字符串y)
,从技术上讲,它不是一个方法。我提到的所有其他东西都是关于.NET库的。@Jeppe它甚至比这个更大……甚至
操作符==