ChatGPT解决这个技术问题 Extra ChatGPT

MySQL VARCHAR 长度和 UTF-8

在 MySQL 中,如果我在 UTF-8 表中创建一个新的 VARCHAR(32) 字段,这是否意味着我可以在该字段中存储 32 个字节的数据或 32 个字符(多字节)?

@naXa:我没有。你觉得我应该?
我不知道。)这是你的问题,这取决于你。我只是想说“另一个答案看起来更完整”。
@robsch 之前接受的答案简单而正确。但是按照大众的要求,我已经接受了你想要的。

i
informatik01

这个答案出现在我的谷歌搜索结果的顶部,但不正确。

混淆可能是由于正在测试不同版本的 MySQL。

版本 4 计数字节

版本 5 计数字符

这是官方 MySQL 5 documentation 的引述:

MySQL 以字符单位解释字符列定义中的长度规范。 (在 MySQL 4.1 之前,列长度以字节为单位解释。)这适用于 CHAR、VARCHAR 和 TEXT 类型。

有趣的是(我没想到)varchar 列的最大长度受 utf8 影响,如下所示:

MySQL 5.0.3 及更高版本中 VARCHAR 的有效最大长度取决于最大行大小(65,535 字节,在所有列之间共享)和使用的字符集。例如,utf8 字符每个字符最多需要三个字节,因此可以将使用 utf8 字符集的 VARCHAR 列声明为最多 21,844 个字符。


布朗先生,感谢您提及这一点。一个 VARCHAR(10) 字段(使用 utf8mb4)可以存储“💩💩💩💩💩💩💩💩💩💩”(10 堆便便),即 10 个字符但 40 个字节。
这个。这是唯一正确的答案。太多的人相信版本 4 的行为是福音。
接受的答案对于 MySQL 5 也是正确的——插入的数字实际上是全角字符集的一部分,并且是多字节 unicode 字符,正如他插入“32 多字节数据”的海报所提到的那样。很遗憾被很多人误解。
引用以下来源,我相信 utf8 字符目前最多需要 6 个字节,因此介于 1 到 6 个字节之间。这导致字符最大值为 10922 的最坏情况。我认为。 joelonsoftware.com/articles/Unicode.html
@usumoio 目前,MySQL 似乎使用 UTF-8 的 3 字节变体,并计划迁移到(标准)4 字节变体:dev.mysql.com/doc/refman/8.0/en/charset-unicode-utf8.html
j
jspcal

它可以让你存储 32 个多字节字符

要使用 UTF-8 节省空间,请使用 VARCHAR 而不是 CHAR。否则,MySQL 必须为 CHAR CHARACTER SET utf8 列中的每个字符保留三个字节,因为这是可能的最大长度。例如,MySQL 必须为 CHAR(10) CHARACTER SET utf8 列保留 30 个字节。

http://dev.mysql.com/doc/refman/5.0/en/charset-unicode.html


我几乎从不使用 CHAR,而且当我这样做时,它并不打算存储多字节字符,所以我很安全。 VARCHAR 怎么样,您确定限制是在多字节字符中定义的,而不是在单字节字符中定义的吗?
@jspcal:UTF-8 每个字符最多使用 4 个字节,而不是 3 个。或者 MySQL 不支持所有 4 个字节?
@RemyLebeau您对utf8是正确的,但对于MySQL却不是。各种 utf8_xxx 字符集最大为 3 字节。 utf8mb4_xxx 占用 4 字节字符。 dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb4.html
随着时间的推移,MySQL 似乎最终会使用标准的 4 字节版本(但在撰写本文时还没有):dev.mysql.com/doc/refman/8.0/en/charset-unicode-utf8.html
A
Alix Axel

varchar(32) 的 32 个 多字节 数据与排序规则 utf8_unicode_ci,我刚刚使用 XAMPP 进行了测试。

1234567890123456789012345678901234567890

截断为:

12345678901234567890123456789012

请记住,这些不是常规的 ASCII 字符。


在 UTF-8 标准 ASCII 字符中,只能存储在一个字节中 - 要真正测试这一点,您需要在测试字符串中实际使用一些多字节(即非 ascii)字符。
这是错误的,至少对于 MySQL 5+。为 varchar 或 char 指定列大小时,以字符为单位指定。我相信 VARCHAR(32) 列的实际大小为 32x3+1=97 字节。
@rjmackay '12345' 不是标准的 ASCII 字符。 en.wikipedia.org/wiki/…
我将 40 个 unicode 字符插入 DB,并在 32 个字符处被截断。但看起来人们认为我使用了 ascii 字节并被截断为 32 个字节。难怪,我投了反对票,哈哈。
@ButtleButkus“我相信 VARCHAR(32) 列的实际大小将是 32x3+1=97 字节”如果你使用 utf8 会这样,但是你会在 MySQL 中得到破坏的 Unicode 支持。您应该改用 utf8mb4 编码,因为有 max. 4 bytes in a utf-8 char,而不是 MySQL 的 utf8 变体中的 3...
N
Nudge

对于高频更新的表,最好使用“char”,因为行的总数据长度将是固定的且快速的。 Varchar 列使行数据大小动态化。这对 MyISAM 不利,但我不知道 InnoDB 和其他人。例如,如果您有一个非常窄的“类型”列,最好将 char(2) 与 latin1 字符集一起使用以仅占用最小空间。


我已经读过,如果表中的任何列都是 varchar,那么您将失去拥有 char 列的所有好处。基本上,您似乎必须在表中使用所有 varchar 或所有 char 以获得最大收益。不过,我不知道这是不是真的。
对于 MyISAM,CHARsome 参数。对于 InnoDB,还有很多其他的事情正在发生,以至于“动态/固定行大小”的争论本质上是无关紧要的。
恕我直言,这里的重点是对于非常小的长度,使用 CHAR 可能是有益的。
L
Laurent Lyaudet

如果您使用 latin1 编码(例如使用 PHP)连接到数据库以将 PHP UTF8 字符串保存在 MySQL UTF8 列中,您将获得双重 UTF8 编码。

如果 UTF8 字符串 $s 的长度为 32 个字符但长度为 64 个字节,并且列是 VARCHAR(32) UTF8,则双重编码会将字符串 $s 转换为 64 个字符长的 UTF8 字符串,该字符串将在数据库中截断为$s 的前 32 个字节对应的前 32 个字符。您最终可能会认为 MySQL 5 的行为类似于 MySQL 4,但实际上它是导致相同结果的第二个原因。