【问题标题】:Mixing UTF8 and latin1_bin fields in MySQL with PHP将 MySQL 中的 UTF8 和 latin1_bin 字段与 PHP 混合
【发布时间】:2011-12-15 19:23:51
【问题描述】:

在数据库中,我必须将名称等存储在 UTF8 中,并将哈希值存储在 latin1_bin 中。我打电话给SET NAMES utf8,但我注意到当我尝试读取它们时它破坏了latin1 字段(我能够很好地编写它们)。这很奇怪,因为如果我理解正确,查询只是关于向服务器发送数据,而不是接收它。

phpMyAdmin 也会显示损坏的数据。

关于我可能做错了什么的任何线索?

(使用 MAMP 1.9.6)

编辑:this 答案指定这也是用于将数据发送回客户端的字符集。我很困惑:如果指定列的字符集无论如何都会被忽略,那又有什么意义呢?

编辑: 列定义摘录:

  `tok` char(64) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
  `sal` char(16) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
...
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_roman_ci ;

查询摘录:

SELECT tok,sal FROM user WHERE id=4 LIMIT 1

.

INSERT INTO user (tok, sal) VALUES (x'1387ea0c22277d3000bd23241c357e3a9ba45a2e28f50581d63a73bf785a7458a95cca4de27d0a86588f5bdfa94415d6a255c2c0379ebc2f00dacba03ae6b866', x'8fca28a592c29f245ff0a3ba5f97420c')

【问题讨论】:

  • 你的哈希列是如何定义的,你的读/写查询是什么样的?
  • @Jon: 更新了列和查询的摘录
  • 读取时如何处理传入的值?这应该可以工作:echo bin2hex(iconv("UTF-8", "ISO-8859-1", $sal)).
  • @Jon:如果我尝试这样做,我只会得到空字符串。
  • @Jon: mb_convert_encoding 将其转换为 something,但仍然不是正确的值。

标签: mysql encoding mamp


【解决方案1】:

您应该更改表定义以使用 MySql 的 BINARY 类型,它非常适合此类数据:

BINARY 和 VARBINARY 类型类似于 CHAR 和 VARCHAR,除了 它们包含二进制字符串而不是非二进制字符串。那 也就是说,它们包含字节字符串而不是字符串。这 表示它们没有字符集,排序和比较是 基于值中字节的数值。

列定义将变为:

`tok` binary(64) NOT NULL,
`sal` binary(16) NOT NULL,

【讨论】:

    【解决方案2】:

    在保持SET NAMES 开启且INSERT 查询不变的情况下,我将SELECT 查询更改为:

    SELECT BINARY(tok) AS tok, BINARY(sal) AS sal FROM user WHERE id=4 LIMIT 1
    

    即我将哈希字段转换为二进制。

    虽然这可行,但如果有人提供(也许更正确?)替代方案,我会保持打开状态。

    【讨论】:

    • 我认为表定义上的sal binary(16) NOT NULL 会更正确,但在这里不会有什么不同。你能检查一下吗?如果它解决了问题,那就是恕我直言“正确的”解决方案。
    • @Jon:是的,这行得通,谢谢 :) (你能把它作为答案发布,以便我接受吗?)
    【解决方案3】:

    set names ... 只设置连接的字符集(仅限客户端!)用于发送和接收数据。它与数据库中字段的编码无关!它仅与您用作数据库客户端的编码有关,例如在 PHP 中。数据库引擎将始终将表中的编码转换为set names ...查询中指定的编码。

    因此,在表定义中,您只需根据需要为每个字段指定编码,并且您不会更改使用 set names ... 命令的方式 - 它只是保持与以前相同。

    【讨论】:

    • 我不明白:那我该如何混合不同的编码?
    • @lohoris,只需在create tablealter table 命令中指定编码即可。然后,在客户端连接期间,两种不同的编码将被转换为set names ... 中指定的连接编码(这意味着连接编码必须能够包含所有使用的编码,所以如果你有非常不同的编码,你可能需要使用 utf-8 作为连接编码)。
    • 为什么这篇文章被否决了?我多年来一直使用这种方法并且它有效。在投反对票时发表评论是一种良好文化的一部分。
    猜你喜欢
    • 1970-01-01
    • 2017-02-17
    • 1970-01-01
    • 2013-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-23
    相关资源
    最近更新 更多