是否有任何 DBMS 具有区分大小写和不区分重音的排序规则?

one*_*hen 18 collation database-agnostic

请注意,此问题与供应商/版本无关

在我看来,作为英语演讲者(打字员、作家),期望单词的大小写正确但不一定具有正确方向的正确口音是合理的:

当我在香榭丽舍大街餐厅的酒店领班克洛伊 (Chloe the maitre d'hotel) 的茶会上沉思时,一边等着 garcon 拿来我炒过的墨西哥胡椒酱……

你明白了。

所以今天我想我想要一个搜索条件来使用区分大小写但不区分重音的排序规则,但找不到。这是否有充分的理由,或者我的只是一个罕见的用例?


这是我正在查看的一些文档的示例(尽管认为供应商/版本不可知):

SQL Server 排序规则名称 (SQL Server 2008 R2)

Sol*_*zky 33

TL; 博士

没有“供应商不可知”的排序规则视图,甚至“版本不可知”,因为它们的实现——包括哪些方面可以变得不敏感和它们的命名约定——是特定于供应商的并且随着时间的推移而变化.

以下是我所发现内容的摘要,详细信息位于该行下方较长的部分:

RDBMS        Naming-             Combinations    Case-Sensitive and
             convention          of options?     Accent-Insensitive support?
-------      ------------        -------------   -----
SQL Server   _CS, _AI, etc       Yes             Latin1_General_100_CS_AI

DB2          _E{x}, _S{y}, etc   Yes             CLDR181_EO_S1

PostgreSQL   locale: en_US       N/A             unaccent(), not via Collation

MySQL        _cs, maybe _ai      No              No: _cs implies _as & _ci implies _ai
                                                 Yes? Create your own Collation :-)

Oracle       only _CI & _AI      No              No: _AI always implies _CI

SAP ASE      arbitrary: turdict  N/A             No: "AI" always implies "CI"

Informix     locale.codepage     N/A             No: no "AI" via Collations
Run Code Online (Sandbox Code Playgroud)

正如您在图表中所看到的,七个 RDBMS 中的两个通过排序规则本身支持“区分大小写不区分重音”的操作,尽管它们具有不同的命名约定(以及其他一些功能差异)。

一个 RDBMS —— PostgreSQL —— 本身并不支持这种组合,但您仍然可以通过使用unaccent()附加功能去除重音来实现它。

最后四个 RDBMS,其中两个具有类似的选项命名约定,它们本身既不支持这种组合,也没有办法在不编写自己的函数来删除重音/变音符号的情况下实现这一点。MySQL 允许创建您自己的排序规则,但这要求您随后将其添加到源代码管理中并将其合并到您的测试和部署过程中,以便它可以应用于所有环境中的所有服务器(但仍然是一个非常酷和灵活的选项) . SAP ASE 提到 SAP可以提供额外的 Unicode 排序顺序,但没有提及他们可能愿意提供的内容。

关于:

这是否有充分的理由,或者我的只是一个罕见的用例?

我可以说,在为这个答案做研究时,我遇到了很多人想要 MySQL 不区分大小写和重音的例子,但很少有人要求你想要的组合。


我想要一个搜索条件来使用区分大小写但不区分重音的排序规则,但找不到。
...
这个问题与供应商/版本无关

您的搜索没有成功,因为根据整理规范寻找 RDBMS 没有任何意义。这不是排序规则的工作方式。虽然您希望将此作为与供应商无关的方法来处理,但现实情况是排序规则——至少我们与之交互的部分——是非常特定于供应商的,并且并不总是适合您正在搜索的方案.

字符串比较和排序非常复杂,执行这些规则有不同的方法。一种方法是使用考虑一个或多个规则的映射。因此,区分大小写和重音的 Sensitive 和 Insensitive 的四种组合将等同于四个单独的映射。例如,您在SQL Server Collat​​ion Name 的MSDN 页面上看到了这一点。如果向下滚动,您将看到图表的左列是Sort Order ID. 每个排序规则都有不同的 ID:SQL_Latin1_General_Cp1_CI_AS= 52 而SQL_Latin1_General_Cp1_CS_AS= 51,尽管唯一的区别是区分大小写。

或者,它可以是基于规则的,例如 Unicode 通过 Unicode Collat​​ion Algorithm (UCA) 提供的内容。在这种方法中,默认情况下,每个字符都被赋予一个或多个权重。然后,每个文化/语言环境都可以选择覆盖任何这些权重,或删除规则或添加规则。该算法会考虑任何特定于语言环境的规则,然后可能会根据选择的任何选项(敏感性,在进行区分大小写的排序时首先出现哪种情况等)来操纵这些权重。这就是为什么 Unicode 排序比非 Unicode 排序慢一点的原因之一。

要了解真正有多少选项(即实际复杂性),请查看 ICU(Unicode 国际组件)项目中的此演示:

ICU 整理演示

有8个不同的选项来指定,其中一些得到你所想的(例如归类名规范的多个元素表示CSCIASAI,等)。考虑到有多少变体,使用每个组合都有自己的 ID 的映射文件方法将导致数千个文件。每当这些特定语言发生变化或发现错误时,其中许多文件都需要更新。这可能就是为什么在 SQL Server 2012 中只有 75 种类型的排序规则(即名称以 开头的排序规则SQL_)。因此没有组合_CS_AI

为什么找不到基于 UCA 的排序规则的组合?好吧,SQL Server 2012 中有 3810 个排序规则不以 开头SQL_,因此总共有 3885 个排序规则。该列表似乎太长而无法在网页上完整列举。但这并不能完全解释为什么您找不到其他供应商的这种组合。

除了已经提到的内容(即要实现的组合太多,要列出的实现太多),您仍然需要应对特定于供应商的实现。意思是:并非所有供应商都允许定制所有这些选项,而且排序规则首先没有标准命名约定。此外,并非所有供应商都将排序选项视为排序规则的一部分:PostgreSQL 排序规则是所选语言环境的默认排序,您需要使用它ILIKE来进行不区分大小写的比较。有关特定于供应商的信息,请参见下文。

SQL Server (微软)

您在这两个 MSDN 文档页面上看到的内容与@MartinSmith 在对该问题的评论中提供的查询之间的区别(下面略有修改):

SELECT *
FROM   sys.fn_helpcollations()
WHERE  [name] LIKE '%[_]CS[_]AI%';
Run Code Online (Sandbox Code Playgroud)

是这两个 MSDN 页面专门指的是非常不推荐使用的 SQL Server 排序规则,而作为该查询结果显示的排序规则(从 SQL Server 2012 SP3 开始,其中 888 个)是 Windows 排序规则。

从 SQL Server 2000 开始,旧的 SQL Server 排序规则(在 SQL Server 能够利用 Windows 排序规则之前创建)已被弃用,并且不会使用新规则或功能进行更新。例如,从 SQL Server 2012 开始,添加了一组排序规则,支持正确处理补充字符的内置函数(即最初在 UCS-2 中定义的“基本”65,536 个字符之外的剩余 UTF-16 字符)。这些较新的排序规则以_SC(如S补充C字符)结尾。

最好不要使用 SQL Server 排序规则 - 名称以SQL_. 因此,您确实可以访问大量支持您正在寻找的选项组合的排序规则(即区分大小写和不区分重音)。只要可用,最好使用一端,_SC只要它具有您想要的所有其他选项。

虽然 SQL Server 确实使用_CS_AI命名约定,但没有所有 3810(截至 SQL Server 2012)Windows 排序规则的列表。只有Windows Collat​​ion Name页面列出了所有区域设置和版本,以及命名约定的工作原理,仅此而已。

SQL Server 还支持切换宽度和假名敏感度。

MySQL(被甲骨文收购)

MySQL的版本5.7,文档指出它不支持_ai_as_ci,和_cs后缀(和_bin的完整性),但也指出:

对于未指定区分重音的非二进制排序规则名称,由区分大小写决定。也就是说,如果排序规则名称不包含_ai_as_ci则顾名思义_ai_cs顾名思义_as

例如,latin1_general_ci不区分大小写(隐式不区分重音),区分大小写(隐式区分latin1_general_cs重音)

这当然意味着可以有一个latin1_general_cs_ai排序规则。然而,MySQL的50年5月5日服务器,我有机会获得不具有多个后缀的排序规则,并且唯一的后缀我看到的是:_cs_ci,和_bin跨越198级总排序规则。我使用了SHOW COLLATION命令来列出它们。

因此,虽然听起来 MySQL 使用了类似的命名约定(至少就这两个选项而言),但我找不到与您要查找的内容匹配的排序规则。但是,有可能去除重音(和其他变音符号)并使用_cs排序规则来获得您想要的内容(类似于您在 PostgreSQL 中的做法——见下文)。但我不确定这个选项,目前没有时间进一步研究。

或者,您可以创建自己的排序规则来完全按照您的意愿行事。与其他 RDBMS 不同,MySQL 似乎使添加自己的排序规则变得相当简单,在这种情况下,您可以完全控制每个字符的权重。有关更多详细信息,请参阅向 8 位字符集添加简单排序规则向 Unicode 字符集添加 UCA 排序规则

有关 MySQL 如何处理不同类型的排序规则的更多信息,请参阅他们的排序规则实现类型页面。

PostgreSQL

PostgreSQL 中的排序规则似乎不太灵活。您只指定文化/区域设置:en_USde_DE等。有关详细信息,请参阅他们的文档页面以获取校对支持。因此,在默认情况下你得到的特定的文化覆盖,但排序规则,否则一切敏感(其中,顺便说一句,是一样的“二进制”排序)。

您可以使用ILIKE(第 9.7.1 节)来实现不区分大小写,但它们没有类似的用于区分重音的运算符。但是,我发现它们确实具有非重音功能,可用于去除重音和其他变音符号。请注意,此功能是附加提供的模块,因此不一定存在于任何特定的 PostgreSQL 服务器中以供使用。最近链接的文档指出:

从源代码分发构建时,这些组件不会自动构建,除非您构建“世界”目标
……
如果您使用的是 PostgreSQL 的预打包版本,则这些模块通常作为单独的子包提供,例如postgresql 贡献。

如果您没有并想要它,请参阅该文档以获取有关如何获取该功能的说明。

还可以在以下 Stack Overflow 回答中找到更多信息:

PostgreSQL 是否支持“不区分重音”的排序规则?

DB2 (IBM)

与 Microsoft SQL Server 类似,DB2 有两种类型的排序规则:

  • “SYSTEM”排序规则,使用以下格式指定:SYSTEM_{codepage}_[optional-territory]. 这些不是很灵活,并且似乎不支持对大小写、口音或任何东西的剪裁敏感性。您可以在此处找到支持的排序规则列表:支持的地区代码和代码页

  • 基于 Unicode 整理算法 (UCA) 的整理。这些确实支持相当多的剪裁。有关如何配置行为、命名约定和有效区域设置列表的详细信息,请参阅他们的基于 Unicode 排序规则算法的排序页面。请注意,在表 1 中,第三行(“案例级别”)中的示例以:

    将 Case Level 属性设置为 on 并且将 Strength 属性设置为primary level 将忽略重音但不忽略大小写。

    这正是您要寻找的。但是,它的语法是: CLDR181_EO_S1. 这就是为什么您的搜索没有找到任何与 DB2 相关的内容。

甲骨文

Oracle 10g 添加了对不区分重音的比较和排序的支持。然而:

  • 他们只能选择表示“不敏感”的操作:_CI_AI
  • 您一次只能指定其中一个选项
  • 不区分大小写的选项 -- _CI-- 仍然区分重音
  • 不区分重音的选项 -- _AI-- “也总是不区分大小写的。” (引自他们的文档,链接如下)

有关更多详细信息和示例,请参阅他们的语言排序和字符串搜索文档页面。

SAP ASE(以前称为 Sybase ASE,又名 Sybase)

ASE 支持每个区域设置/字符集的以下一种或多种敏感性组合:

  • 区分大小写,区分重音
  • 不区分大小写,区分重音
  • 不区分大小写,区分重音,优先顺序
  • 不区分大小写,不区分重音

您可以在“选择默认排序顺序”页面上查看区域设置、字符集和可用排序顺序之间的关系。您可以在其排序规则名称和 ID页面上查看完整的排序规则列表。

它们的排序规则命名约定是任意的,因为它们都是 4 到 8 个字符,并尝试捕获语言环境名称或代码页以及某种排序意义。例如:

altnoacc==“CP 850 Alternative – 无重音”
rusdict==“俄语词典排序”
dynix==“汉语拼音排序”

在他们的Selecting the Default Unicode Sort Order页面上有一条说明:

您可以使用目录中的外部文件添加排序顺序$/collate/Unicode。名称和排序规则 ID 存储在syscharsets. 在syscharsets设置默认 Unicode 排序顺序之前,不必包含外部 Unicode 排序顺序的名称。
...
外部 Unicode 排序顺序由 SAP 提供。不要尝试创建外部 Unicode 排序顺序。

尚不清楚 SAP 是否会提供外部排序顺序以允许区分大小写不区分重音。也许有一天我会给他们发电子邮件并询问是否可以要求一个。

为了获得所需的灵敏度组合,您应该能够创建一个标量用户定义函数来去除重音和其他变音符号。

Informix(由 IBM 购买)

Informix 似乎主要只支持排序规则的默认排序和比较行为。因此,排序规则只是语言环境和字符集。区分大小写在数据库级别处理,默认情况下它们区分大小写。您可以通过在语句中指定 NLSCASE INSENSITIVE将数据库(不是表、列、查询,甚至谓词)设置为不区分大小写CREATE DATABASE

虽然数据库排序规则——语言环境和字符集——可以被每个客户端连接覆盖,但似乎没有办法覆盖区分大小写设置。并且,该NLSCASE选项的名称中有“NLS”是有原因的:它只影响NCHARNVARCHAR数据;CHAR并且VARCHAR总是区分大小写。

没有解决重音敏感问题,也没有删除重音/变音符号的内置功能。

Informix 排序规则命名约定是:

SELECT *
FROM   sys.fn_helpcollations()
WHERE  [name] LIKE '%[_]CS[_]AI%';
Run Code Online (Sandbox Code Playgroud)

在哪里:

  • <lang> = 2 个字母或 3 个字母的语言代码
  • <country> = 2 个字母的国家或地区代码
  • <code set> = 以以下 3 种等效方式之一指定的代码页:
    • 名称: 8859-1
    • IBM CCSID 编号的十进制值: 819
    • IBM CCSID 号的十六进制值: 0333

因此,以下三个语言环境规范均指完全相同的语言环境:

  • fr_fr.8859-1
  • fr_fr.819
  • fr_fr.0333

有关更多信息,请参阅:

  • 抱歉打错字,但我的意思是“着色”,例如蓝色的大写字母和红色的重音......只是在开玩笑!这很容易成为我收到的最好的答案。非常感谢 :) (4认同)