忽略“where”中的重音

lum*_*umo 20 sql-server-2008 sql-server collation select

在我们的数据库中,我们有多个带有 caron/hatschek 的条目。现在我们的用户希望在搜索没有的条目时找到包含 caron/hatschek 的条目。我将通过一个简单的例子来说明这一点:

在我们的数据库中,我们有条目(联系人姓名)

Millière
Run Code Online (Sandbox Code Playgroud)

所以这个名字在这个人居住的国家是正确的。

在我们国家,我们没有任何带有 caron/hatschek 的字符,因此我们的用户搜索Milliere. 没有结果出现,因为è显然不匹配e

我不知道这是如何实现的,因为é, èê还有更多可用的(这只是字母的一个例子e......)。

(另一种方法会容易得多,因为我可以简单地将所有带有 caron/hatschek 的字母替换为基本字母。显然,我们的用户确实想要数据库中名称的正确版本,而不是残缺的名称。)

Tom*_*m V 33

这个问题可以使用不区分重音的排序规则来解决。

您的数据库可能正在使用 AS(Accent Sensitive)排序规则,因此默认情况下它将搜索包括重音在内的完全匹配项。

您可以通过在比较中指定排序规则来指示 WHERE 子句使用除数据库默认值之外的其他排序规则。

这个 dbfiddle 中,我创建了一个使用 LATIN1 排序规则的示例,但您可以使用与您正在使用的排序规则相同的方法,只需将 AS 更改为 AI 以用于您的列当前使用的排序规则。

使用与列使用的排序规则相匹配的 Accent Insensitive 排序规则。例如,如果列正在使用SQL_Latin1_General_CP1_CI_AS、使用SQL_Latin1_General_CP1_CI_AI和不使用Latin1_General_CI_ASLatin1_General_100_CI_AS或这两者的任何变体,因为非 SQL_ 排序规则的行为将在更多方面有所不同,而不仅仅是重音不敏感,这可能不是用户所期望的。

您可以在sys.columns.

CREATE TABLE testaccent (name nvarchar(50));
GO
INSERT INTO testaccent (name) VALUES ('Millière') , ('Milliere');
GO
-- returns Miliere
SELECT * FROM testaccent WHERE name = 'Milliere';

-- returns both
SELECT * FROM testaccent WHERE name='Milliere' COLLATE Latin1_General_CI_AI

--only returns Miliere
SELECT * FROM testaccent WHERE name='Milliere' COLLATE Latin1_General_CI_AS
Run Code Online (Sandbox Code Playgroud)

通读使用 SQL Server 排序规则以获取更多信息。

然后,您可能希望使用此排序规则进行排序(如评论中指出的peufeu),以确保“é”与“e”排序。否则,按字母顺序对结果进行分页的人会惊讶于没有在他们期望的位置找到“é”,但是如果您只想触摸此查询,您也可以将COLLATE子句添加到 the 中ORDER BY

正如Solomon Rutzky在评论中指出的那样,如果这仅影响 1 列或几列,另一种选择是创建一个非持久化计算列,该列简单地重复“名称”列并提供不区分重音的排序规则,然后对计算出的列进行索引柱子。这避免了由于更改查询内的排序规则而导致的扫描。然后查询需要过滤新列。

就像是:

ALTER TABLE 
dbo.[table_name] ADD [SearchName] datatype_of_name_column 
AS ([Name] COLLATE LATIN1_GENERAL_100_CI_AI)); 

CREATE INDEX [IX_table_name_SearchName] 
ON dbo.[table_name] ([SearchName] ASC);
Run Code Online (Sandbox Code Playgroud)

或者你也可以创建一个视图而不是添加一个计算列(就像jyao喜欢的那样)。