我需要在我的Rails应用程序的现有表中添加一个新的整数列。该列只能有值1,2,3,所以我想为表/列添加一个检查约束。如何在Rails迁移中指定此约束?如何在Rails迁移中添加检查约束?
回答
Rails的迁移不提供任何方法来添加约束,但你仍然可以通过迁移,但是通过将实际的SQL执行()
创建迁移文件做到这一点:
ruby script/generate Migration AddConstraint
现在,迁移文件:
class AddConstraint < ActiveRecord::Migration
def self.up
execute "ALTER TABLE table_name ADD CONSTRAINT check_constraint_name CHECK (check_column_name IN (1, 2, 3))"
end
def self.down
execute "ALTER TABLE table_name DROP CONSTRAINT check_constraint_name"
end
end
我刚刚通过获取PostgreSQL CHECK约束来工作。
Nilesh的解决方案并不完整; db/schema.rb文件将不包含约束,因此测试和任何使用db:setup的部署都不会获得约束。按照http://guides.rubyonrails.org/migrations.html#types-of-schema-dumps
虽然在迁移,您可以执行自定义SQL语句时, 模式自卸车无法重建从数据库中那些语句。 如果您正在使用这样的功能,那么您应该将架构 格式设置为:sql。
即,在配置/ application.rb中设置
config.active_record.schema_format = :sql
不幸的是,如果你使用PostgreSQL装载产生的转储时,你可能会得到一个错误,请参阅ERROR: must be owner of language plpgsql讨论。我不想在这个讨论中关注PostgreSQL配置路径;再加上在任何情况下,我喜欢有一个可读的db/schema.rb文件。所以这为我排除了迁移文件中的自定义SQL。
Valera建议的宝石https://github.com/vprokopchuk256/mv-core似乎很有前途,但它只支持一组有限的约束(当我尝试使用它时,我得到了一个错误,虽然这可能是由于与我包括的其他宝石不兼容) 。
我想要的解决方案(hack)是让模型代码插入约束条件。由于它是kindof就像一个验证,这就是我所说的那样:
class MyModel < ActiveRecord::Base
validates :my_constraint
def my_constraint
unless MyModel.connection.execute("SELECT * FROM information_schema.check_constraints WHERE constraint_name = 'my_constraint'").any?
MyModel.connection.execute("ALTER TABLE my_models ADD CONSTRAINT my_constraint CHECK (...the SQL expression goes here ...)")
end
end
当然这并各个验证之前一个额外的选择;如果这是一个问题,解决方法是将它放在“连接后”猴子补丁中,如How to run specific script after connected to oracle using rails?(您不能简单地缓存select的结果,因为验证/约束添加发生在可能获得的事务中回滚,所以你需要检查每一次。)
你可以使用Migration Validators gem。查看详情这里:https://github.com/vprokopchuk256/mv-core
随着创业板,你就可以在数据库级别定义包含验证:
def change
change_table :table_name do |t|
t.integer :column_name, inclusion: [1, 2, 3]
end
end
而且您能够定义如何验证这应该定义,甚至错误消息应显示:
def change
change_table :posts do |t|
t.integer :priority,
inclusion: { in: [1, 2, 3],
as: :trigger,
message: "can't be anything else than 1, 2, or 3" }
end
end
你甚至可以提升等级从迁移该验证正确的模型:
class Post < ActiveRecord::Base
enforce_migration_validations
end
,然后验证迁移定义也将被定义为加载ActiveModel验证您的模型:
Post.new(priority: 3).valid?
=> true
Post.new(priority: 4).valid?
=> false
Post.new(priority: 4).errors.full_messages
=> ["Priority can't be anything else than 1, 2, or 3"]
您可以使用Sequel
宝石https://github.com/jeremyevans/sequel
Sequel.migration do
change do
create_table(:artists) do
primary_key :id
String :name
constraint(:name_min_length){char_length(name) > 2}
end
end
end
我刚刚出版了宝石本:active_record-postgres-constraints。由于README有描述,您可以用DB/schema.rb文件中使用它,并把它添加支持的迁移下面的方法:
create_table TABLE_NAME do |t|
# Add columns
t.check_constraint conditions
# conditions can be a String, Array or Hash
end
add_check_constraint TABLE_NAME, conditions
remove_check_constraint TABLE_NAME, CONSTRAINT_NAME
注意,在这个时候,Postgres的唯一支持。
- 1. Laravel迁移 - 添加检查约束表
- 2. 如何添加检查约束迁移笨的PostgreSQL
- 3. 检查DataRow约束添加
- 4. 如何使用Laravel的迁移将约束添加到表中?
- 5. 运行rails迁移时无法添加外键约束错误
- 6. “检查约束被一些行违反” 添加检查约束
- 7. Rails的迁移:删除约束
- 8. Ruby on Rails:如何使用迁移向现有列添加非空约束?
- 9. 在迁移中的唯一索引列上添加空约束
- 10. 如何在实体框架中为JSON添加检查约束?
- 11. 如何在SQL Server中添加检查约束?
- 12. Postgres 9.2 - 添加条件约束检查
- 13. SQL添加外键约束与检查
- 14. 如何向表中添加检查约束?
- 15. 如何添加约束检查表中的列值
- 16. 改变表添加约束与改变表添加检查约束
- 17. 如何通过迁移将“唯一”约束添加到已存在的索引
- 18. 检查约束Grails数据库迁移脚本
- 19. laravel迁移模式构建器:延迟约束检查
- 20. 添加约束在Xcode 6中查看
- 21. 在NHibernate中检查约束
- 22. 在MySQL中检查约束?
- 23. Django迁移下降,并重新添加相同的约束
- 24. Laravel“无法添加外键约束” - 迁移
- 25. 使用Laravel迁移添加外键约束
- 26. 通过迁移不起作用添加唯一约束
- 27. 添加迁移出错 - 错误的约束列名称?
- 28. 南自动迁移添加错误的唯一约束
- 29. Laravel 5.2委托迁移错误,无法添加外键约束
- 30. Laravel 4迁移 - 不能添加外键约束
另外请注意,如果你添加一个约束,你必须在`config/application.rb`中将`config.active_record.schema_format =:sql`设置为[“`db/schema.rb`不能表达数据库特定项目,如触发器,存储过程或检查约束。“](http://edgeguides.rubyonrails.org/active_record_migrations.html#types-of-schema-dumps)。 – 2017-02-13 01:30:25
现在有一个支持在`db/schema.rb`中存储约束的gem:[active_record-postgres-constraints](https://github.com/on-site/active_record-postgres-constraints)。查看我的答案了解更多详情。目前,只支持postgres。 – 2017-03-17 13:51:14