MySQL VARCHAR长度和UTF-8


84

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


@naXa:我没有。你觉得我应该吗?
Alix Axel 2014年

我不知道。)这是您的问题,由您决定。我只是想说“另一个答案看起来更完整”。
naXa 2014年

@robsch先前接受的答案很简单且正确。但是根据大众需求,我已经接受了您想要的那个。
Alix Axel

Answers:


168

这个答案出现在我的Google搜索结果的顶部,但不正确,所以:

混乱可能是由于测试了不同版本的mysql。

  • 版本4计数字节
  • 版本5包含字符

http://dev.mysql.com/doc/refman/5.0/zh-CN/string-type-overview.html

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

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

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


48
布朗先生,感谢您提到这一点。VARCHAR(10)字段(使用utf8mb4)可以存储“💩💩💩💩💩💩💩💩💩💩”(10堆便便),即10个字符,但40个字节。
basic6 2014年

3
这个。这是唯一正确的答案。太多的人认为版本4的行为是福音。
布伦丹·伯德

2
公认的答案对于MySQL 5也是正确的-插入的数字实际上是全角字符集的一部分,并且是多字节的unicode字符,正如张贴者所说的那样,他插入了“ 32个多字节数据”。许多人误解了,真是可惜。
user193130

引用以下来源,我相信utf8字符当前最多需要6个字节,因此介于1到6个字节之间。这会导致最坏的情况,最大字符数为10922。我认为。 joelonsoftware.com/articles/Unicode.html
usumoio

1
@usumoio当前,看起来MySQL使用3字节的UTF-8变体,并计划迁移到(标准)4字节的变体:dev.mysql.com/doc/refman/8.0/en/charset-unicode -utf8.html
flow2k

8

它会让您存储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,您确定限制是在多字节字符中定义的,而不是在单字节字符中定义的吗?
Alix Axel

9
@jspcal:UTF-8每个字符最多使用4个字节,而不是3个。还是MySQL不支持所有4个字节?
雷米·勒博

4
@RemyLebeau您对utf8是正确的,但不适用于MySQL。各种utf8_xxx字符集最多为3个字节。utf8mb4_xxx包含4个字节的字符。dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb4.html
Buttle Butkus,

随着时间的推移,MySQL似乎最终将使用标准的4字节版本(但在撰写本文时尚未使用):dev.mysql.com/doc/refman/8.0/en/charset-unicode-utf8 .html
flow2k

6

我使用XAMPP测试了32个多字节的varchar(32)排序规则数据utf8_unicode_ci

1234567890123456789012345678901234567890

被截断为:

12345678901234567890123456789012

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


4
在UTF-8中,标准ASCII字符仅存储在一个字节中-要真正测试此字符,您需要在测试字符串中实际使用一些多字节(即非ascii)字符。
rjmackay 2013年

5
至少对于MySQL 5+,这是错误的。当指定varchar或char的列大小时,它以字符形式指定。我相信VARCHAR(32)列的实际大小将是32x3 + 1 = 97字节。
Buttle Butkus

5
@rjmackay'12345'不是标准的ASCII字符。en.wikipedia.org/wiki/…–
Alexey Lebedev

7
我在DB中插入了40个unicode字符,并被截断为32个字符。但是看起来人们认为我使用了ascii字节并被截断为32字节。难怪我被选票了,哈哈。

2
@ButtleButkus“我相信VARCHAR(32)列的实际大小为32x3 + 1 = 97字节”如果使用utf8,则会在MySQL中得到残破的Unicode支持。您应该改用utf8mb4编码,因为有最大值。utf-8字符中的4个字节,而不是MySQL的utf8变体中的3个字节...
Stijn de Witt

1

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


1
我已经读过,如果表中的ANY列是varchar,那么您将失去拥有char列的所有好处。基本上,看来您必须使用表中的所有varchar或所有char才能获得最大收益。不过,我不知道这是真的。
Buttle Butkus

对于MyISAM,有一些论点CHAR。对于InnoDB,还有许多其他事情正在进行,因此“动态/固定行大小”的争论本质上是无关紧要的。
里克·詹姆斯

恕我直言,这里的重点是,对于非常小的长度,使用可能会有所帮助CHAR
ToolmakerSteve

0

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.