在第一次迁移时,我在列 content
上声明为字符串
Activerecord 根据注释 gem 将其设置为 string(255)。
在我将应用程序推送到使用 postgres 的 Heroku 后,如果我在内容中的表单中输入长度超过 255 的字符串,我会收到错误
PGError: ERROR: value too long for type character varying(255)
问题是我需要该内容包含一个可能非常长的字符串(自由文本,可能是数千个字符)
- pg 会接受什么变量(字符串不适合这个)?
- 如何创建迁移来替换该列的类型,
谢谢
At the first migration, I declared on a column content
to be string
Activerecord made it to be string(255) according to annotate gem.
After I push the app to heroku, which uses postgres, if I enter in the form in content a string longer than 255 I get the error
PGError: ERROR: value too long for type character varying(255)
Problem is I need that content to contain a string that is extremely long perhaps (free text, could be thousands of chars)
- What variable (is string is not appropriate for this) would pg accept?
- How do I create a migration to replace the type of that column
thanks
发布评论
评论(2)
如果您想要一个没有长度限制的字符串,您应该将
text
与 Rails 一起使用。像这样的迁移:应该解决问题。您可能需要
:null => false
或最后的一些其他选项。当您使用没有显式限制的
string
列时,Rails 将添加隐式:limit => 255.
.但如果您使用text
,您将获得数据库支持的任意长度字符串类型。 PostgreSQL 允许您使用没有长度的varchar
列,但大多数数据库为此使用单独的类型,而 Rails 不知道没有长度的varchar
。您必须在 Rails 中使用text
来获取text
列。在 PostgreSQL 中,text
类型的列和varchar
类型的列之间没有区别(但是varchar(n)
是 不同)。此外,如果您在 PostgreSQL 之上进行部署,则根本没有理由使用:string
(又名varchar
),数据库会处理text
> 和varchar(n)
内部相同,除了varchar(n)
的额外长度限制;如果您有外部约束(例如政府表格表明表格 897/B 上的字段 432 将长度为 23 个字符)的列大小。顺便说一句,如果您在任何地方使用
string
列,则应始终指定:limit
来提醒自己存在限制,并且应该进行验证在模型中确保不超过限制。如果超过限制,PostgreSQL会抱怨并引发异常,MySQL会悄悄地截断字符串或抱怨(取决于服务器配置),SQLite会让它按原样通过,其他数据库会做其他事情(可能会抱怨) 。此外,您还应该在同一个数据库(通常是 Heroku 的 PostgreSQL)之上进行开发、测试和部署,甚至应该使用相同版本的数据库服务器。数据库之间还存在其他差异(例如 GROUP BY 的行为),ActiveRecord 不会使您免受这些差异的影响。你可能已经这样做了,但我想我还是要提一下。
更新:较新版本的 ActiveRecord 确实可以无限制地理解
varchar
,因此,至少对于 PostgreSQL,您可以说:更改
而
varchar(n)
> 列转换为varchar
。text
和varchar
就 PostgreSQL 而言仍然是同一件事,但某些表单构建器会以不同的方式对待它们:varchar
得到一个text
则获取多行You should use
text
with Rails if you want a string with no length limit. A migration like this:should sort things out. You might want
:null => false
or some other options on the end of that too.When you use a
string
column without an explicit limit, Rails will add an implicit:limit => 255
. But if you usetext
, you'll get whatever arbitrary length string type the database supports. PostgreSQL allows you to use avarchar
column without a length but most databases use a separate type for that and Rails doesn't know aboutvarchar
without a length. You have to usetext
in Rails to get atext
column in PostgreSQL. There's no difference in PostgreSQL between a column of typetext
and one of typevarchar
(butvarchar(n)
is different). Furthermore, if you're deploying on top of PostgreSQL, there's no reason to use:string
(AKAvarchar
) at all, the database treatstext
andvarchar(n)
the same internally except for the extra length constraints forvarchar(n)
; you should only usevarchar(n)
(AKA:string
) if you have an external constraint (such as a government form that says that field 432 on form 897/B will be 23 characters long) on the column size.As an aside, if you are using a
string
column anywhere, you should always specify the:limit
as a reminder to yourself that there is a limit and you should have a validation in the model to ensure that the limit is not exceeded. If you exceed the limit, PostgreSQL will complain and raise an exception, MySQL will quietly truncate the string or complain (depending on the server configuration), SQLite will let it pass as-is, and other databases will do something else (probably complain).Also, you should also be developing, testing, and deploying on top of the same database (which will usually be PostgreSQL at Heroku), you should even use the same versions of the database server. There are other differences between databases (such as the behavior of GROUP BY) that ActiveRecord won't insulate you from. You might be doing this already but I thought I'd mention it anyway.
Update: Newer versions of ActiveRecord do understand
varchar
without a limit so, with PostgreSQL at least, you can say:to change a
varchar(n)
column tovarchar
.text
andvarchar
are still the same thing as far as PostgreSQL is concerned but some form builders will treat them differently:varchar
gets an<input type="text">
whereastext
gets a multi-line<textarea>
.虽然接受的答案非常好,但我想在这里添加一个答案,希望对于像我这样的非专家来说,可以更好地处理原始海报问题第 2 部分。
生成脚手架迁移
您可以通过在控制台中键入内容来生成迁移来保存更改(只需将
表
替换为您的表名称,column
表示您的列名称)这将在您的 Rails 应用程序 /db/migrate/ 文件夹中生成框架迁移。此迁移是您的迁移代码的占位符。
例如,我想创建一个迁移,以将名为 TodoItems 的表中的列类型从
string
更改为text
:运行迁移
输入代码以更改列后,只需运行:
应用迁移。如果您犯了错误,您可以随时使用以下方法恢复更改:
Up 和 Down 方法
接受的答案引用
Up
和Down
方法,而不是较新的Change
方法。自 Rails 3.2 以来,提出了旧式 Up 和 Down 方法与较新的 Change 方法相比有一些优点。 “向上和向下”避免ActiveRecord::IrreversibleMigration 异常
。自 Rails 4 发布以来,您可以使用可逆
为了避免这个错误:享受 Rails :)
While the accepted answer is excellent, I wanted to add an answer here that hopefully better deals with the original posters question part 2, for non experts like myself.
generating scaffold migration
You can generate a migration to hold your change by typing in your console (just replace the
table
for your tables name, andcolumn
for you column name)This will generate skeleton migration inside you Rails application /db/migrate/ folder. This migration is a placeholder for your migration code.
For example I want to create a migration to change the type of a column from
string
totext
, in a table called TodoItems:Running your migration
Once you've entered the code to change the column just run:
To apply your migration. If you make an error you can always revert the change with:
Up and Down methods
The accepted answer references
Up
andDown
methods, instead of the newerChange
method. Since rails 3.2 old style Up and Down Methods presented a few advantages over the newer Change method. 'Up and Down' avoidActiveRecord::IrreversibleMigration exception
. Since the release of Rails 4 you can usereversible
to avoid this error:Enjoy Rails :)