-->

MySQL的非法归类组合(MySQL Illegal mix of collations)

2019-06-27 17:27发布

看我的督促日志后,我有一些错误mentionning:

[2012-08-31 15:56:43] request.CRITICAL: Doctrine\DBAL\DBALException: 
An exception occurred while executing 'SELECT t0.username ....... FROM fos_user t0 WHERE t0.username = ?'
with params {"1":"Nrv\u29e7Kasi"}:

SQLSTATE[HY000]: General error: 1267 Illegal mix of collations (latin1_swedish_ci,IMPLICIT)
and (utf8_general_ci,COERCIBLE) for operation '=' 

Alghout我有原则CFG下UTF-8的默认:

doctrine:
    dbal:
        charset:  UTF8

看来,我的所有的MySQL表是在latin1_swedish_ci ,所以我的问题是:

我可以手动更改排序规则utf8_general_ci为我所有表无任何并发症/预防措施?

Answer 1:

它有助于了解以下定义:

  • 一种字符编码的细节每个符号是如何以二进制表示(并因此存储在计算机)。 例如,符号é (U + 00E9,拉丁小字母E急性)被编码为0xc3a9在UTF-8 (其MySQL调用utf8 )和0xe9在视窗-1252 (其MySQL调用latin1 )。

  • 字符集是可使用一个给定的字符编码表示符号的字母表。 令人困惑的是,这个术语也用来指相同的字符编码。

  • 归类是上一个字符集的排序,以使字符串进行比较。 例如:MySQL的latin1_swedish_ci整理对待一个角色等同于基本字符的最重音的变化,而其latin1_general_ci整理将在下一个基本字符前预订他们,但不等同(还有其他更显著,差异太大:比如订单的类似的字符åäöß )。

MySQL将决定哪些归类下如记录,应适用于给定表达式表达的整理 :特别是一个列的排序规则将优先于字符串文字的。

WHERE您的查询的WHERE子句比较以下字符串:

  1. 在一个值fos_user.username ,在列的字符集(视窗-1252)并表示其核对的优先编码latin1_swedish_ci (为2的可压缩性的值); 同

  2. 字符串文字'Nrv⧧Kasi' ,在该连接的字符集编码(UTF-8,作为被配置成通过学说)并表示该连接的核对的偏好utf8_general_ci (具有4可压缩性值)。

由于第一这些字符串的具有比第二低的可压缩性的值时,MySQL试图执行使用该字符串的归类的比较: latin1_swedish_ci 。 要做到这一点,MySQL的尝试将第二个字符串转换为latin1 -但因为汉字不在该字符集存在,比较失败。


警告

每个人都应该停顿了一会儿考虑列当前如何编码:您试图筛选记录,其中fos_user.username等于包含不能在该列中存在的字符的字符串!

如果您认为该列中确实含有此类字符,那么你可能写的,而连接字符编码列设置的东西(如latin1 )造成的MySQL来解释所接收的字节序列这些都是在Windows-1252字符字符集。

如果是这样的情况下,继续之前的任何进一步的你应该解决您的数据!

  1. 这样的列转换成被上数据插入使用的字符编码,如果不同的现任编码:

     ALTER TABLE fos_users MODIFY username VARCHAR(123) CHARACTER SET foo; 
  2. 通过将它们转化到滴与这样的列相关联的编码信息binary字符集:

     ALTER TABLE fos_users MODIFY username VARCHAR(123) CHARACTER SET binary; 
  3. 与这样的列中的数据实际上是由将它们转换为相关的字符组传输的编码相关联。

     ALTER TABLE fos_users MODIFY username VARCHAR(123) CHARACTER SET bar; 

需要注意的是,如果来自多字节编码转换,则可能需要增加塔的尺寸(或甚至改变其类型),以便以适应转换字符串的最大可能长度。


一旦一个肯定的是,列正确编码,一个可能迫使比较由下述其中使用Unicode排序规则来进行

  • 值显式转换fos_user.username为Unicode字符集:

     WHERE CONVERT(fos_user.username USING utf8) = ? 
  • 迫使字符串文字具有比柱的下部可压缩值(将导致列的值,以UTF-8的隐式转换):

     WHERE fos_user.username = ? COLLATE utf8_general_ci 

或者人们可以像你说的,永久的列(S)转换为Unicode编码并设置适当的整理。

我可以手动更改排序规则utf8_general_ci为我所有表无任何并发症/预防措施?

原则考虑的是Unicode编码占用比单字节字符集更多的空间,所以:

  • 更多的存储可能需要;

  • 比较可能比较慢; 和

  • 索引前缀长度可能需要被调整(注意,最多是在字节,因此比以前可表示更少的字符)。

此外,要注意的是,在作为记录ALTER TABLE语法 :

要更改默认的表字符集和所有字符列( CHARVARCHARTEXT )改为新的字符集,使用这样的语句:

  ALTER TABLE tbl_name转换为字符集。 语法 ; 

对于具有的数据类型的列VARCHAR或一个TEXT类型CONVERT TO CHARACTER SET将改变数据类型必须确保新列足够长,以尽可能多的字符存储为原始列。 例如,一个TEXT列具有两个长度字节,值的字节长度存储在列中,最多为65,535。 对于latin1 TEXT列中,每个字符需要一个字节,所以列可以存储多达65,535个字符。 如果列被转换成utf8 ,每个字符可能需要多达三个字节,对于3×65535 = 196605字节的最大可能长度。 该长度将不适合在一个TEXT列的长度字节,所以MySQL将数据类型转换为MEDIUMTEXT ,这是最小的字符串类型,其长度字节可以记录的196605值。 类似地, VARCHAR柱可能被转换到MEDIUMTEXT

为了避免上述类型的数据类型的变化,不要使用CONVERT TO CHARACTER SET 。 相反,使用MODIFY来改变各列。



Answer 2:

那就对了。 我就遇到了这个问题,最好的快速和快速的解决方案是

         CONVERT(fos_user.username USING utf8)


Answer 3:

简单地转换表的字符由命令设置如下,

ALTER TABLE tbl_name CONVERT TO CHARACTER SET utf8;


文章来源: MySQL Illegal mix of collations