在Rails中,字符串(string)和文本(text)有什么区别?

482

我正在使用Rails制作一个新的Web应用程序,并且想知道stringtext之间有什么区别?何时应该使用每个?

9个回答

574

区别在于符号在查询语言中如何转换为相应的列类型。

使用MySQL: string映射到VARCHAR(255)

:string |                   VARCHAR                | :limit => 1 to 255 (default = 255)  
:text   | TINYTEXT, TEXT, MEDIUMTEXT, or LONGTEXT2 | :limit => 1 to 4294967296 (default = 65536)

参考资料:

https://hub.packtpub.com/working-rails-activerecord-migrations-models-scaffolding-and-database-completion/

何时应使用每个数据类型?

一般来说,对于短文本输入(如用户名、电子邮件、密码、标题等),请使用:string,对于预期较长的输入(如描述、评论内容等),请使用:text


14
我认为更好的经验法则是始终使用:text。请参见http://www.depesz.com/2010/03/02/charx-vs-varcharx-vs-varchar-vs-text/。 - Reed G. Law
85
对于MySQL来说,可以在varchars上创建索引,但不能在text上创建。 - Omar Qureshi
20
PostgreSQL 实现更偏好文本。对于 PostgreSQL 中的字符串/文本,唯一的区别是字符串有长度限制。在性能方面没有差异。 - wurde
1
这似乎不是 ActiveRecord 的全部情况。在 MySQL 中将值 true 保存到 varchar (即 string 类型字段) 中会将该值序列化为 1 (这是完全合理的)。然而,在 text 类型中,将值 “true” 存储会将其序列化为单个字符 t。我迁移了一列却没有意识到这一点,现在所有将来的行中值为 true 的都变成了 t。有人对此行为有任何见解吗? - Peter
那么 @OmarQureshi 这是什么意思呢?是说在文本列上使用“where”子句比字符串列要慢得多吗? - elliotwesoff
1
@elli0t 这意味着您将无法进行索引。如果这很重要,那么您不应该在MySQL上使用文本。 - Omar Qureshi

178

如果你正在使用PostgreSQL,请尽可能使用text类型,除非有大小限制,因为在text和varchar之间没有性能惩罚。

这三种类型之间没有性能差异,除了在使用空格填充类型时增加的存储空间以及在存储到长度约束列时检查长度所需的一些额外CPU周期。虽然在其他一些数据库系统中,character(n)具有性能优势,但在PostgreSQL中没有此类优势;事实上,由于其额外的存储成本,character(n)通常是最慢的。在大多数情况下,应改用text或character varying类型。

PostgreSQL手册


5
为了实现数据库无关性,这是否是最佳方法?如果您想更改数据库怎么办?我承认,在现实世界中这种情况并不经常发生,但是...... 如果没有“性能差异”,为什么不坚持使用字符串来处理短文本,使用文本来处理长文本呢?考虑到您自己的评论对字符串进行索引,这仍然似乎是最佳方法。 - Dan Barron
8
在现实世界中,可能有很多原因使得放弃“任何问题都只有一个真正解决方案”的观念成为必要。 - Dan Barron
22
可能是这样,但是数据库不可知性是一个虚假的预言者。 - Omar Qureshi
2
有没有人知道性能惩罚是否显著,还是这是过早优化的情况?我猜你永远不会注意到任何差异,而段落开头似乎也证实了这一点:“这三种类型之间没有性能差异”。 - Dennis
5
你提出了一个好观点,但我还没有完全被说服。那篇博客文章中使用text类型而不是(n)数据类型的论据很有说服力,但使用text而不是varchar的论点并非如此。他说它们是一样的,但更喜欢使用text是因为varchar可能会与varchar(n)混淆,并且因为输入text比较少字符。但是,如果使用text代替varchar, 你会失去存储数据不应过长这个上下文信息。例如,用text存储用户名对我来说似乎有误导性。 - Dennis
显示剩余4条评论

18

在你的数据库中,字符串被翻译为 "Varchar",而文本被翻译为 "text"。一个 varchar 可以包含远少于 text 的项目,而 text 可以是(几乎)任意长度。

有关详细分析和良好参考,请查看 http://www.pythian.com/news/7129/text-vs-varchar/

编辑:一些数据库引擎可以一次性加载varchar,但将 text(和 blob)存储在表格之外。当使用nametext时,SELECT name, amount FROM products可能会比使用varchar要慢得多。由于 Rails 默认会使用 SELECT * FROM... 加载记录,因此你的文本列将被加载。虽然这在你的或我的应用程序中可能永远不会是真正的问题(过早优化是...),但知道 text 并不总是“免费”的是很好的。


13

如果大小是固定的且较小,则使用字符串;如果大小是可变的且较大,则使用文本。 这非常重要,因为文本比字符串要大得多。它包含了更多的千字节。

因此,对于小字段始终使用字符串(varchar)。例如:first_name、login、email、文章或帖子的主题, 以及文本示例:帖子或文章的内容/正文,段落字段等。

字符串大小为1到255(默认= 255)

文本大小为1到4294967296(默认= 65536)2


12

如上所述,这不仅会影响数据库数据类型,还会影响生成的视图(如果您正在使用脚手架)。
string将生成一个文本框,而text将生成一个文本区域。


4

对于较短的字段,如姓名、地址、电话和公司名称,使用字符串。

对于较大的内容、评论和段落,使用文本。

我的一般规则是,如果是超过一行的内容,我通常选择文本;如果是2-6个短单词,我会选择字符串。

官方规定字符串长度为255。因此,如果您的字符串超过255个字符,请选择文本。


2
最初的回答非常棒,它很好地解释了字符串与文本之间的区别(主要是数据库中的限制大小,但还有其他一些小问题),但我想指出一个小问题,因为那个答案对我来说并不完全适用。
最大大小:限制 => 1到4294967296并没有按照实际情况运行,我需要从该最大大小减去-1。我正在存储大型JSON块,它们有时可能非常巨大。
这是我的迁移,其中包含更大的值以及MySQL不会抱怨的值。
请注意,在限制的末尾5而不是6
class ChangeUserSyncRecordDetailsToText < ActiveRecord::Migration[5.1]
  def up
    change_column :user_sync_records, :details, :text, :limit => 4294967295
  end

  def down
    change_column :user_sync_records, :details, :string, :limit => 1000
  end
end

1
对于那些使用PostgreSQL并希望存储JSON数据的人来说,最好使用本地的jsonb类型(但首先要检查您的PostgreSQL版本)。 - Maxim Khan-Magomedov

1
如果您正在使用Oracle... STRING 将被创建为 VARCHAR(255) 列,而 TEXT 则是一个 CLOB
NATIVE_DATABASE_TYPES = {
    primary_key: "NUMBER(38) NOT NULL PRIMARY KEY",
    string: { name: "VARCHAR2", limit: 255 },
    text: { name: "CLOB" },
    ntext: { name: "NCLOB" },
    integer: { name: "NUMBER", limit: 38 },
    float: { name: "BINARY_FLOAT" },
    decimal: { name: "DECIMAL" },
    datetime: { name: "TIMESTAMP" },
    timestamp: { name: "TIMESTAMP" },
    timestamptz: { name: "TIMESTAMP WITH TIME ZONE" },
    timestampltz: { name: "TIMESTAMP WITH LOCAL TIME ZONE" },
    time: { name: "TIMESTAMP" },
    date: { name: "DATE" },
    binary: { name: "BLOB" },
    boolean: { name: "NUMBER", limit: 1 },
    raw: { name: "RAW", limit: 2000 },
    bigint: { name: "NUMBER", limit: 19 }
}

https://github.com/rsim/oracle-enhanced/blob/master/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb


0
如果属性与表单中的f.text_field匹配,请使用string,如果匹配f.text_area,请使用text

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接