Ruby on rails Rails what';s唯一索引中的差异并验证的唯一性
首先,有人能解释一下唯一索引在数据库中是如何工作的吗 假设我有一个带有Ruby on rails Rails what';s唯一索引中的差异并验证的唯一性,ruby-on-rails,postgresql,indexing,Ruby On Rails,Postgresql,Indexing,首先,有人能解释一下唯一索引在数据库中是如何工作的吗 假设我有一个带有名称列的用户模型,我在其上添加了一个唯一索引,但在模型(User.rb)中,名称字段上有一个存在验证器 所以现在当我试图创建两个同名用户时,我得到了一个错误 重复的键值违反唯一约束“索引用户名称” 因此,在我看来,它就像唯一性索引与唯一性验证器一样工作(?) 如果是,那么外键呢 假设我有Post模型,其中属于:user与用户有多个:Post。 以及posts表中具有唯一索引的外键用户id。那么多篇文章不能有相同的用户id 有人
名称列
的用户模型,我在其上添加了一个唯一索引
,但在模型(User.rb)中,名称
字段上有一个存在
验证器
所以现在当我试图创建两个同名用户时,我得到了一个错误
重复的键值违反唯一约束“索引用户名称”
因此,在我看来,它就像唯一性索引
与唯一性验证器一样工作(?)
如果是,那么外键呢
假设我有Post
模型,其中属于:user
与用户有多个:Post
。
以及posts表中具有唯一索引的外键用户id
。那么多篇文章不能有相同的用户id
有人能解释一下唯一索引的工作原理吗
我使用Ruby 2.0.0运行Rails 4 以下是唯一索引和验证的唯一性之间的区别
这是一个补丁,使ActiveRecord能够识别数据库生成的唯一违反约束的错误。例如,它在不声明validates_university_的情况下执行以下操作:
create_table "users" do |t|
t.string "email", null: false
end
add_index "users", ["email"], unique: true
class User < ActiveRecord::Base
end
User.create!(email: 'abc@abc.com')
u = User.create(email: 'abc@abc.com')
u.errors[:email]
=> "has already been taken"
create_表“users”do|t|
t、 字符串“email”,null:false
结束
添加索引“用户”[“电子邮件”],唯一:true
类用户“已采取行动”
好处是速度快、易用性和完整性--
速度
使用这种方法,您不需要在保存时执行db查找来检查唯一性(当缺少索引时,这有时会非常缓慢--)。如果您真的关心验证唯一性,那么无论如何都必须使用数据库约束,这样无论发生什么情况,数据库都将验证唯一性,并且这种方法将删除一个额外的查询。检查索引两次对DB来说不是问题(它第二次被缓存),但是从应用程序中节省DB往返是一个巨大的胜利
易用性
考虑到无论如何都必须有db约束才能实现真正的唯一性,这种方法将让一切在db约束就位后自动发生。如果愿意,您仍然可以使用的validates\u university\u
完整性
validates_university_of一直有点麻烦——它无法正确处理竞争条件,并导致必须使用冗余的错误处理逻辑来处理的异常。(请参阅中的“并发性和完整性”一节)
验证唯一性的唯一性不足以确保值的唯一性。其原因是,在生产中,多个工作进程可能会导致竞争条件:
两个并发请求尝试创建具有相同名称的用户(和
我们希望用户名是唯一的)
服务器上的请求由两个工作进程接受,这两个工作进程
现在将并行处理它们
这两个请求都扫描users表,并查看名称是否正确
可用
这两个请求都通过了验证,并创建了一个具有
可用名称
如需更清晰的理解,请勾选此项
如果为列创建唯一索引,则意味着您可以保证表中不会有多个该列具有相同值的行。在模型中仅使用validates\u university\u验证不足以强制唯一性,因为可能会有并发用户尝试创建相同的数据
假设两个用户试图使用相同的电子邮件注册一个帐户,您在用户模型中添加了validates\u university\u of:email。如果同时点击“注册”按钮,Rails将在用户表中查找该电子邮件,并回复说一切正常,可以将记录保存到表中。Rails随后将使用同一封电子邮件将这两条记录保存到用户表中,现在您需要处理一个非常糟糕的问题
要避免这种情况,还需要在数据库级别创建一个唯一的约束:
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :email
...
end
add_index :users, :email, unique: true
end
end
class CreateUsers
因此,通过创建索引用户电子邮件唯一索引,您可以获得两个非常好的好处。数据完整性和良好的性能,因为唯一索引往往非常快
如果在用户id的posts表中输入unique:true,则不允许输入具有相同用户id的重复记录。至于唯一性
唯一性验证属性的值在之前是唯一的
对象被保存。它不会在中创建唯一性约束
数据库,因此可能会发生两个不同的数据库连接
为要创建的列创建两个具有相同值的记录
要独一无二。为了避免这种情况,您必须在这两者上创建一个唯一的索引
数据库中的列
此外,如果您只是在模型级别验证了
的唯一性,那么您将被限制从rails端插入重复记录,而不是在数据库级别。
通过dbconsole的SQL注入查询将毫无问题地插入重复记录
当您说您在“posts”表中的“user_id”上创建了一个索引为的外键时,默认情况下rails只在其上创建一个索引
,而不是唯一索引
。如果您有1-M关系,那么在您的案例中,唯一索引中就没有任何意义
如果“用户id”的posts表中有unique:true
那么,就不可能用相同的“用户id”复制记录