当我们在MySQL中创建一个带有VARCHAR列的表时,我们必须为它设置长度。但对于TEXT类型,我们不需要提供长度。

VARCHAR和TEXT之间有什么区别?


博士TL;

TEXT

固定最大大小为65535字符(你不能限制最大大小) 占用2 + c字节的磁盘空间,其中c是存储字符串的长度。 不能(完全)成为索引的一部分。我们需要指定一个前缀长度。

转换为(M)

可变最大大小M个字符 M需要在1到65535之间 占用1 + c字节(当M≤255时)或2 + c字节(当256≤M≤65535时)的磁盘空间,其中c是存储字符串的长度 可以成为索引的一部分吗

更多的细节

TEXT的最大长度固定为2¹6 -1 = 65535个字符。 VARCHAR的最大变量为M = 2¹-1。 所以你不能选择文本的大小,但你可以选择VARCHAR。

另一个区别是,不能在TEXT列上放置索引(全文索引除外)。 如果你想在列上有一个索引,你必须使用VARCHAR。但是请注意,索引的长度也是有限的,因此如果您的VARCHAR列太长,您必须在索引中只使用VARCHAR列的前几个字符(请参阅CREATE index的文档)。

但是如果你知道可能的输入字符串的最大长度只有M,例如一个电话号码或一个名字或类似的东西,你也想使用VARCHAR。然后你可以使用VARCHAR(30)而不是TINYTEXT或TEXT,如果有人试图保存所有三个“指环王”书籍的文本在你的电话号码列,你只存储前30个字符:)

编辑:如果你想要存储在数据库中的文本超过65535个字符,你必须选择MEDIUMTEXT或LONGTEXT,但要小心:MEDIUMTEXT存储的字符串最多为16mb, LONGTEXT存储的字符串最多为4gb。如果您使用LONGTEXT并通过PHP获取数据(至少如果您使用mysqli而不使用store_result),则可能会得到内存分配错误,因为PHP试图分配4 GB内存以确保整个字符串可以被缓冲。在PHP以外的其他语言中也可能发生这种情况。

但是,您应该始终检查输入(是否太长?是否包含奇怪的代码?)然后将其存储在数据库中。

Notice: For both types, the required disk space depends only on the length of the stored string and not on the maximum length. E.g. if you use the charset latin1 and store the text "Test" in VARCHAR(30), VARCHAR(100) and TINYTEXT, it always requires 5 bytes (1 byte to store the length of the string and 1 byte for each character). If you store the same text in a VARCHAR(2000) or a TEXT column, it would also require the same space, but, in this case, it would be 6 bytes (2 bytes to store the string length and 1 byte for each character).

要了解更多信息,请参阅文档。

最后,我想添加一个注意事项,TEXT和VARCHAR都是变长数据类型,因此它们很可能将存储数据所需的空间最小化。但这需要性能的权衡。如果需要更好的性能,则必须使用固定长度的类型,如CHAR。你可以在这里阅读更多相关内容。


在上面的回答中有一个重要的细节被忽略了。

MySQL对每一行的最大大小施加了65,535字节的限制。 VARCHAR列的大小按照最大行大小计算,而TEXT列则假设通过引用存储数据,因此它们只需要9-12个字节。这意味着即使VARCHAR字段的“理论”最大大小是65,535个字符,如果您的表中有多个列,则无法实现这一目标。

还要注意,VARCHAR字段所需的实际字节数取决于列(和内容)的编码。MySQL将最大可能使用的字节数计算为最大行大小,因此如果您使用像utf8mb4这样的多字节编码(您几乎肯定应该这样做),它将使用更多的最大行大小。

更正:不管MySQL如何计算最大行大小,VARCHAR/TEXT字段数据是否实际存储在行中或通过引用存储取决于您的底层存储引擎。对于InnoDB,行格式会影响这种行为。(感谢Bill-Karwin)

使用TEXT的原因:

如果您想存储一段或更多文本 如果您不需要索引该列 如果已达到表的行大小限制

使用VARCHAR的原因:

如果你想储存几个单词或一个句子 如果您想索引(整个)列 如果要使用带有外键约束的列