在 Latin1 数据库中存储 UTF8 文本的后果是啥?
Posted
技术标签:
【中文标题】在 Latin1 数据库中存储 UTF8 文本的后果是啥?【英文标题】:What are the ramifications of storing UTF8 text in a Latin1 database?在 Latin1 数据库中存储 UTF8 文本的后果是什么? 【发布时间】:2018-06-21 00:33:27 【问题描述】:我有一个默认字符集latin1
的mysql数据库
mysql> SELECT SCHEMA_NAME 'database', default_character_set_name 'charset', DEFAULT_COLLATION_NAME 'collation' FROM information_schema.SCHEMATA ;
+--------------------+---------+-------------------+
| database | charset | collation |
+--------------------+---------+-------------------+
| dbname12345 | latin1 | latin1_swedish_ci |
驱动程序,在本例中为 knex + node-mysql,配置为charset: 'utf8'
。因此,驱动程序以 UTF8 对文本进行编码、存储和检索。
然而,mysql 认为数据在latin1
。像这样混合字符集的后果是什么?
【问题讨论】:
如果将 UFT8 存储到 latin1 中,则会遇到编码问题。 什么编码问题?请更具体 UFT8 可以存储 latin1 无法存储的字符.. 取 UTF8 字符串asdf ®´
。如果我们用 utf8 将该字符串编码为 ASCII 字节,我们会得到asdf \xc2\xae\xc2\xb4
,它作为十六进制字节是6173646620c2aec2b4
。如果我们使用 latin1 对字符串进行编码,我们会得到 asdf \xae\xb4
ASCII 字节或 6173646620aeb4
十六进制字节。 Mysql 只是简单地存储和检索这些字节。如果我们的驱动程序知道如何将这些字符串编码和解码为这些字节,那么 mysql 字符集是什么又有什么关系呢?
@david_adler "Unicode is a superset of ASCII" 所以有些字符可以存储在 unicode 中,而不能存储在 latin1 中。在这种情况下,使用非拉丁字符(例如普通话),不可能将其存储在 latin1 编码中。
【参考方案1】:
对 title 问题的简短回答是,可以将 latin1 和 utf8 的 common 的 256 个字符放入 CHARACTER SET
的任一列中。但是,您必须清楚您使用的是什么编码。否则®
可能会显示为®
(“Mojibake”)。
不,SELECT
为该数据库中的任何 新 表获取 默认。它不控制列的存储方式。
数据库有一个新表的默认值。
该表具有新列的默认值。
该列具有CHARACTER SET
的true 定义。
所以,请执行SHOW CREATE TABLE
并查看列。如果列未指定字符集,则查看位于输出末尾的表的默认值。 (还有一种方法可以从 information_schema.COLUMNS
获取此信息,但这种方法比较笨拙。)
®
是 latin1 中的十六进制 AE
或 utf8(或 utf8mb4)中的 C2AE
。该字符在“ascii”字符集中不存在,它在 7 位处停止。
但是,由于®
存在于latin1
和utf8
中,您可以安全地在两种编码之间来回切换。也就是说,如果你告诉 MySQL 正确的东西。
client 中的编码在SET NAMES
或连接参数中指定。如果客户端有AE
,则必须指定latin1;如果客户端有C2AE
,则必须指定utf8。
同时,列(不是表,也不是数据库)可以是 latin1 或 utf8。如果需要,转换将在您 INSERT
和 SELECT
时完成。
注意:latin1 只有 256 种不同的编码,没有中文,没有 Emoji,除了西欧字符几乎没有。
今后,最好定义大多数列utf8mb4
。否则,可能会显示一堆便便(?
)????
。
如果遇到问号、Mojibake等,请咨询Trouble with UTF-8 characters; what I see is not what I stored
【讨论】:
以上是关于在 Latin1 数据库中存储 UTF8 文本的后果是啥?的主要内容,如果未能解决你的问题,请参考以下文章