3

这是一个奇怪的难题,AFAIK utf8_bin 应该保证每个口音都正确存储在数据库中,即没有一些奇怪的 ASCII 转换。所以我有这样的表:

DEFAULT CHARSET=utf8 COLLATE=utf8_bin

然而,当我尝试根据 MySQL 比较/查询/诸如“Krąków”和“Kraków”之类的条目时,这是同一个字符串。

出于好奇,我还尝试了 utf8_polish,MySQL 声称对于波兰人来说,“a”和“ą”没有任何区别。

那么如何设置 MySQL 表,这样我就可以安全地存储 unicode 字符串,而不会丢失重音等?

服务器:MySQL 5.5 + openSUSE 11.4,客户端:Windows 7 + MySQL Workbench 5.2。

更新——创建表

CREATE TABLE `Cities` (
  `city_Name` VARCHAR(145) CHARACTER SET utf8 NOT NULL,
  PRIMARY KEY (`city_Name`)
) DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

请注意,我不能为列设置不同的utf8_bin,因为整个表都是 utf8_bin,所以实际上列的排序规则被重置为默认值。

4

2 回答 2

2

该解决方案的所有学分都归于 bobince,因此请对我的问题发表评论。

这个问题的解决方案有点奇怪,我会冒着风险说 MySQL 在这方面被破坏了。

所以,假设我用 utf8 创建了一个表并且没有为列做任何事情。后来我意识到我需要严格比较字符,所以我将表和列的排序规则更改为 utf8_bin。解决了?

不,现在 MySQL 看到了——表确实是 utf8_bin,但列也是 utf8_bin,这意味着列使用表的 DEFAULT 排序规则。然而 MySQL 并没有意识到以前的默认值与当前的默认值不同。因此比较仍然不起作用。

因此,您必须摆脱列的默认值,使其超出排序规则“family”范围的某个外来值(如果“utf8xxx”表示没有其他“utf8xxx”)。一旦摆脱它,并且您在列排序规则中看到没有说“默认”的条目,您可以设置 utf8_bin,它现在评估为默认值,但是由于我们来自非默认排序规则,所以一切都按预期进行。

不要忘记在每一步应用更改。

于 2013-02-17T21:11:18.543 回答
0

MySQL 默认字符集和排序规则(它们是服务器范围的,但可以根据连接进行更改)在创建表时应用。创建表后更改默认值不会影响现有表。

字符集和排序规则是各个列的属性。它们可以从表范围的默认值中设置,但它们确实属于列。

一个 utf8 字符集应该足以允许正确表示所有欧洲语言。您绝对应该能够将“a”和“±”存储为两个不同的字符。

utf8-bin 的排序规则产生区分大小写和重音字符的排序规则。

以下是文本值和整理行为之间差异的一些示例。我使用了三个示例字符串:'abcd'、'ĄBCD' 和 'ąbcd'。最后两个有 A-ogonek 字母。

第一个示例表明,使用 utf8 字符表示和 utf8_general_ci 排序规则,三个字符串分别按照用户指定的方式显示,但它们比较相等。在不区分 a 和 ± 的排序规则中,这是可以预料的。这是一个典型的不区分大小写的排序规则,其中所有变体字符的排序等于没有任何变音符号的字符。

SET NAMES 'utf8' COLLATE 'utf8_general_ci';
SELECT 'abcd', 'ąbcd' , 'abcd' < 'ąbcd',  'abcd' = 'ąbcd';
                               false            true  

下一个示例显示在不区分大小写的波兰语排序规则中,a 在 ą 之前。我不懂波兰语,但我怀疑波兰电话簿中的 As 和 Ą 是分开的。

SET NAMES 'utf8' COLLATE 'utf8_polish_ci';
SELECT 'abcd', 'ĄBCD' , 'ąbcd', 'abcd' < 'ĄBCD', 'abcd' < 'ąbcd' , 'ąbcd' = 'ĄBCD' 
                                      true             true              true

下一个示例显示了 utf8_bin 排序规则会发生什么。

SET NAMES 'utf8' COLLATE 'utf8_bin';
SELECT 'abcd', 'ĄBCD' , 'ąbcd', 'abcd' < 'ĄBCD', 'abcd' < 'ąbcd' , 'ąbcd' = 'ĄBCD' 
                                      true           true               false

在这种情况下,需要注意一件不直观的事情。'abcd' < 'ĄBCD' 为真(而纯 ASCII 的 'abcd' < 'ABCD' 为假)。如果你从语言上思考,这是一个奇怪的结果。这是因为两个 A-ogonek 字符在 utf8 中的二进制值都高于所有 abc 和 ABC 字符。所以:如果你对 ORDER BY 操作使用 utf8-bin 排序规则,你会得到语言上奇怪的结果。

您是说“Krąków”和“Kraków”比较相等,您对此感到困惑。当使用的排序规则是 utf8_general_ci 时,它们确实比较相等。但他们不使用 utf8_bin 或 utf8_polish_ci。根据 MySQL 对波兰语的支持,城市名称的这两种拼写是不同的。

当你设计你的应用程序时,你需要理清你希望这一切在语言上如何工作。“Krąków”和“Kraków”是同一个地方吗?“Ąaron”和“Aaron”是同一个人吗?如果是这样,您需要 utf8_general_ci。

您可以考虑更改显示的表格,如下所示:

  ALTER TABLE Cities
MODIFY COLUMN city_Name 
              VARCHAR(145)
              CHARACTER SET utf8 
              COLLATE utf8_general_ci

这将按照您想要的方式设置表格中的列。

于 2013-02-17T15:13:27.153 回答