Latin1数据库中的UTF-8数据:可以保存吗?

Pet*_*rdk 5 mysql unicode ruby-on-rails character-encoding latin1

我有一个rails应用程序,可以从Android设备接收数据.我注意到有些数据在日语时没有正确保存.它在MySQL客户端和rails网站中显示为文字问号(不是钻石问号).

事实证明,我连接到rails应用程序的数据库设置为Latin1.Rails设置为UTF-8.

我读了很多关于字符编码的内容,但他们都提到数据在某种程度上有点可读.然而我的只是文字问号.尝试使用Web上的几种方法将数据转换为UTF-8也不会改变事情.我怀疑数据在写入数据库时​​会转换为问号.

MySQL控制台的示例输出:

select * from foo where bar = "foobar";
+-------+------+------------------------+---------------------+---------------------+
| id    | name | bar                    | created_at          | updated_at          |
+-------+------+------------------------+---------------------+---------------------+
| 24300 | ???? | foobar                 | 2012-01-23 05:04:22 | 2012-01-23 05:04:22 |
+-------+------+------------------------+---------------------+---------------------+
1 row in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)

我的rails应用程序从Android客户端获取的输入数据是:

name = ????
Run Code Online (Sandbox Code Playgroud)

在保存到数据库之前,已经验证此输入数据存在于rails应用程序中.因此,它不会在Android客户端或传输到服务器期间受损.我有机会获得这些数据吗?还是完全迷失了?

egg*_*yal 6

实际上很容易认为数据是以一种方式编码的,当它实际上以其他方式编码时:这是因为任何直接检索数据的尝试都会导致首先转换为数据库连接的字符集,然后转换为输出媒体的字符集 - 因此您应首先通过SELECT BINARY name FROM foo WHERE bar = 'foobar'或验证存储数据的实际编码SELECT HEX(name) FROM foo WHERE bar = 'foobar'.

?预期字符的位置,您可能会找到以下字节序列之一:

  • 0xe78886,表明您的列实际上包含UTF-8编码数据:这通常发生在最初插入文本的数据库连接的字符集设置为latin1但实际发送了UTF-8编码数据时.

    ?在获取数据时必须看到字符,因为数据存储和显示之间的某些内容无法对这些字节进行转码(但是,鉴于MySQL认为它们代表爆并且这些字符可能在大多数字符集中可用,因此它不太可能发生在MySQL本身内 - 除非你在检索过程中明确调整编码信息).

    无论如何,如果是这种情况,您需要从列中删除编码信息,然后告诉MySQL数据实际编码为UTF-8.如ALTER TABLE语法下所述:

    警告 

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

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

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

  • 0x3f,表明数据库确实包含文字字符?并且您的原始数据已丢失:这不容易发生,因为如果隐式转码导致数据丢失,MySQL通常会抛出错误1366.也许在insert语句中有一些显式转码?

    在这种情况下,您需要将存储编码转换为合适的格式,然后更新或重新插入数据:

    ALTER TABLE foo CONVERT TO utf8;
    UPDATE foo SET name = _utf8 '????' WHERE bar = 'foobar';
    
    Run Code Online (Sandbox Code Playgroud)