将 MySQL 中的 UTF8 和 latin1_bin 字段与 PHP 混合使用

发布于 2024-12-11 18:28:06 字数 989 浏览 0 评论 0原文

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

phpMyAdmin 也显示损坏的数据。

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

(使用 MAMP 1.9.6)

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

编辑: 列定义摘录:

  `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')

On a database I'll have to store names and such in UTF8, and hashes in latin1_bin. I called SET NAMES utf8, but I noticed that it corrupted the latin1 fields when I tried to read them (I was able to write them just fine). Which is odd, since if I understood correctly that query is only about sending data to the server, not receiving it.

phpMyAdmin displays broken data too.

Any clue about what I might be doing wrong?

(using MAMP 1.9.6)

edit: this answer specifies this is also the charset used to send data back to the client. I'm getting confused: what's the point of specifying the charset of a column if that will be ignored anyway?

edit:
excerpt from the column definition:

  `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 ;

excerpt from queries:

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

.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

笑红尘 2024-12-18 18:28:06

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

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

列定义将变为:

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

You should change your table definition to use MySql's BINARY type, which is the perfect fit for this kind of data:

The BINARY and VARBINARY types are similar to CHAR and VARCHAR, except
that they contain binary strings rather than nonbinary strings. That
is, they contain byte strings rather than character strings. This
means that they have no character set, and sorting and comparison are
based on the numeric values of the bytes in the values.

The column definitions would become:

`tok` binary(64) NOT NULL,
`sal` binary(16) NOT NULL,
心舞飞扬 2024-12-18 18:28:06

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

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

set names ... only sets the character set of the connection (of the client side only!) for both sending and receiving the data. It is not related to the encoding of the fields in the database! It is only related to the encoding which you use as a client to the database, e.g. in PHP. The database engine will always convert the encoding between the encoding in tables to the encoding specified in set names ... query.

So in table definition you just specify encoding for each field as you need, and you don't change anything in the way how you used the set names ... command - it just remains the same as before.

忆沫 2024-12-18 18:28:06

保持 SET NAMES 开启,并且 INSERT 查询保持不变,我将 SELECT 查询更改为:

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

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

虽然这有效,但我会保持开放状态,以防有人提供(也许更正确?)替代方案。

Leaving SET NAMES on, and the INSERT query intact, I changed the SELECT query to:

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

i.e. I casted the hash fields to binary.

While this worked, I'll leave this open in case someone provides a (perhaps more correct?) alternative.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文