mysql charsets,我可以在python中执行转换吗?

时间:2013-08-15 00:28:45

标签: mysql unicode encoding utf-8

我有一个包含一些不良数据的MySQL数据库。

我从这个Unicode字符串开始:

u'TECNOLOGÍA Y EDUCACIÓN'

为数据库编码为UTF-8产生:

'TECNOLOG\xc3\x8dA Y EDUCACI\xc3\x93N'

当我将这些字节发送到数据库时,使用连接字符集latin1和数据库字符集utf8(是的,我知道这是错误的,但这已经发生了很多次,并且现在的目标是弄清楚腐败的确切过程,以便可以逆转),数据转换为此(使用BINARY()检查):

'TECNOLOG\xc3\x83\xc2\x8dA Y EDUCACI\xc3\x83\xe2\x80\x9cN'

除了双重编码之外,我期望的结果是:

'TECNOLOG\xc3\x83\xc2\x8dA Y EDUCACI\xc3\x83\xc2\x93N'

大部分都是有意义的,因为它将多字节UTF-8字符解释为latin1,并将每个字节编码为单个字符,但转换为\x93 - > \xe2\x80\x9c毫无意义。 latin1的\x93未转换为UTF-8 \xe2\x80\x9c,但\xe2\x80\x9c可以转换为Unicode,产生u'\u201c',这是CP中的代码点\x93 1252 charset。

在处理转换时,mysql是否结合了latin1和CP-1252?如何在python中完全复制转换过程?我已经迭代了系统上的每个编码,但它们都不适用于整个字符串。在python中,我如何从'TECNOLOG\xc3\x83\xc2\x8dA Y EDUCACI\xc3\x83\xe2\x80\x9cN'返回到'TECNOLOG\xc3\x8dA Y EDUCACI\xc3\x93N'?解码为UTF-8将正确处理前3/4,但最后一个是错误的,我尝试的任何内容都不会返回正确的结果。

1 个答案:

答案 0 :(得分:2)

  1.   

    现在的目标是弄清楚腐败的确切过程,以便可以逆转

    正如ALTER TABLE Syntax所述:

      

    警告

         

    CONVERT TO操作会在字符集之间转换列值。如果您在一个字符集中有一列(如latin1),则这不是您想要的,但存储的值实际上使用其他一些不兼容的字符集(如utf8)。在这种情况下,您必须为每个此类列执行以下操作:

    ALTER TABLE t1 CHANGE c1 c1 BLOB;
    ALTER TABLE t1 CHANGE c1 c1 TEXT CHARACTER SET utf8;
    
         

    这样做的原因是当您转换为BLOB列或从BLOB列转换时没有转换。

    在你的情况下:

    1. 将列的编码更改为插入时使用的连接字符集(即latin1),以便存储的字节与最初接收的字节相同:

      ALTER TABLE my_table MODIFY my_column TEXT CHARACTER SET latin1;
      
    2. 然后删除编码信息(通过修改列使其成为二进制字符串):

      ALTER TABLE my_table MODIFY my_column BLOB;
      
    3. 然后应用正确的编码信息(通过修改列使其成为utf8字符集中的字符串):

      ALTER TABLE my_table MODIFY my_column TEXT CHARACTER SET utf8;
      
    4. 小心使用足够长的数据类型以避免数据截断。还要注意确保应用程序代码从此使用正确的连接字符集(否则你最终会得到一个表,其中某些记录以一种方式编码而另一些记录以另一种方式编码,这可能是解决的噩梦)。

      如果您还不能修改数据库,只需在连接字符设置为latin1(但您的应用程序需要UTF-8)时获取数据,就会产生正确的数据。或者,使用CONVERT()

      SELECT CONVERT(BINARY CONVERT(my_column USING latin1) USING utf8)
      FROM   my_table
      
    5.   

      mysql在处理转换时是否合并了latin1和cp1252?

      正如West European Character Sets所述:

        

      MySQL的latin1与Windows cp1252字符集相同。这意味着它与官方ISO 8859-1或IANA(互联网号码分配机构)latin1相同,但IANA latin1处理0x80和{{1}之间的代码点除外作为“未定义”,而0x9f,因此MySQL的cp1252,为这些位置分配字符。例如,latin1是欧元符号。对于0x80中的“未定义”条目,MySQL会将cp1252转换为Unicode 0x810x0081转换为0x8d0x008d转换为0x8f },0x008f0x900x00900x9d