正在尝试将时间戳添加到现有表。根据Api documenation add_timestamps
下面是我在迁移中的代码:
def change
add_timestamps(:products, null: false)
end
获取错误:
*-- add_timestamps(:products, {:null=>false})
rails aborted!
StandardError: An error has occurred, this and all later migrations canceled:
SQLite3::SQLException: Cannot add a NOT NULL column with default value NULL: ALTER TABLE "products" ADD "created_at" datetime NOT NULL*
我也尝试了所有的解决方案在此thread
Rails 5.1.4 Ruby 2.4.0
6条答案
按热度按时间5anewei61#
不能将具有not-null约束的列添加到非空表中,因为表中现有的行将立即具有空值,因此条件失败。
而是分三步引入列:
oyt4ldly2#
在我看来,在迁移中使用ActiveRecord查询甚至SQL操作现有数据是错误的。
正确的rails 5.2+方法是:
这是一个过程,所以你应该能够设置一个日期在过去,如果你想。
来源:https://github.com/rails/rails/pull/20005
dffbzjpn3#
我喜欢@spickermann的方法,因为它考虑到了现有的记录,而且可能您的迁移已经一直进行到生产,他的方法确保了数据的持久性。
尽管如此,你们中的许多人可能会发现自己处于这种情况,但仍处于开发阶段,这意味着没有真实的的敏感数据,你可能会害怕失去......这给了你更多的自由,你可以如何执行表中的更改。
如果您的代码和记录只存在于本地(如果您仍然没有创建记录,跳过步骤1),并且该表是在上次迁移中创建的,我的建议是:
1.-删除该表中的所有记录。
2.-转到您的迁移文件并通过添加
t.timestamps
对其进行编辑,使其看起来像这样:3.-然后转到控制台并输入
rails:db:redo
。正如这里所解释的,该命令是执行回滚然后再次迁移回来的快捷方式。现在,您将看到模式已更新为相应的
created_at
和updated_at
列。这样做的具体好处是它非常容易做到,您不需要创建额外的迁移文件,并且您可以学习使用非常方便的命令;)
ztigrdn84#
我也遇到了同样的问题。我希望最终结果严格等价于新数据库上的
add_timestamps :products
。我没有运行查询来回填,而是完成了一个3步的过程。
它是可逆的。
注意:这是在Rails 6.1和PostgreSQL中实现的
jslywgbw5#
我在rails 5.0上,这些选项都不起作用。
rails:db:redo
可以工作,但对大多数人来说不是一个可行的解决方案。唯一起作用的是
idfiyjo86#
我做了类似于@jeremiemv的操作,只是少了几个步骤,如果在添加带有默认值的时间戳后不更改列默认值,那么默认值将作为迁移运行的时间显示在表结构中。
我的解决方案的不同之处还在于,当您提供默认值时,您不需要管理
null: true
然后false
。Rails 7和MySQL