我应该如何编写activerecord迁移来反映这一点:
CREATE TABLE table (
c1 data_type,
c2 data_type,
c3 data_type,
UNIQUE (c2, c3)
);
这在一列上添加了唯一约束,但我想要的是在两列的组合上创建唯一约束,就像在多列上创建唯一约束一节中所解释的那样。
编辑
更准确地说:我有一个表account和一个表balance_previous_month。
class CreateBalance < ActiveRecord::Migration[6.1]
def change
create_table :balance_previous_month do |t|
t.decimal :amount, :precision => 8, :scale => 2
t.date :value_date
t.belongs_to :account, foreign_key: true
t.timestamps
end
end
end
由于我们是在一月份,所以价值日期(即上月底的余额)是2020-12-31
。
我想在表balance_previous_month上添加一个约束,其中每个account_id
只能有一个给定数量的value_date
。金额可以更新,但给定的帐户不能有两个相同的value_dates。
您添加到另一个帖子的链接并不完全等同于您的请求,因为一个答案谈论通过模型强制唯一性,而另一个谈论使用索引,而在您的示例中,您正在使用约束。(点击这里了解更多关于它们之间区别的信息)
有两个地方可以强制惟一性,应用程序和数据库,也可以同时在两个地方执行。
数据库
所以如果你想通过使用索引来强制唯一性你可以这样写:def change
add_index :table, [:c2, :c3], unique: true
end
如果你想添加约束在您的示例中,您将不得不在迁移中运行直接的SQL查询,因为在rails中没有内置的方法来做到这一点。
def up
execute <<-SQL
ALTER TABLE table
ADD UNIQUE (c2, c3)
SQL
end
查看上面的链接,了解更多关于它们之间区别的信息。
应用
通过模型强制惟一性:
validates :c2, uniqueness: { scope: :c3 }
感谢Daniel Sindrestean,这段代码工作了:
class CreateBalance < ActiveRecord::Migration[6.1]
def change
create_table :balance_previous_month do |t|
t.decimal :amount, :precision => 8, :scale => 2
t.date :value_date
t.belongs_to :account, foreign_key: true
t.timestamps
end
execute <<-SQL
ALTER TABLE balance_previous_month
ADD UNIQUE (account_id, value_date) # ActiveRecord creates account_id
SQL
end
end