为什么PG :: UniqueViolation:错误:重复键值违反了唯一约束?

Ors*_*say 11 ruby postgresql ruby-on-rails

我有一个模型Post,每次创建一个帖子我想要同时创建一个新的实例Moderation.

所以在post.rb中我使用回调after_save :create_moderation 然后写一个私有方法:

 ...
 include Reportable
 after_save :create_moderation

 private
 def create_moderation
    self.create_moderation!(blog: Blog.first)
 end
Run Code Online (Sandbox Code Playgroud)

但是当创建提案时,我收到此错误:

PG :: UniqueViolation:错误:重复键值违反唯一约束"moderations_reportable"DETAIL:键(reportable_type,reportable_id)=(Post,25)已存在.:INSERT INTO"moderations"("blog_id","reportable_type","reportable_id","created_at","updated_at","blog_type")VALUES($ 1,$ 2,$ 3,$ 4,$ 5,$ 6)返回"id"

在reportable.rb我有:

  has_one :moderation, as: :reportable, foreign_key: "reportable_id", foreign_type: "reportable_type", class_name: "Moderation"
Run Code Online (Sandbox Code Playgroud)

然后很少有其他方法可报告对象.

请注意,当我在控制台中运行create方法时,不会发生此问题.

编辑

  create_table "moderations", id: :serial, force: :cascade do |t|
    t.string "reportable_type", null: false
    t.string "reportable_id", null: false
    t.integer "blog_id", null: false
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "blog_type", null: false
    t.string "upstream_moderation", default: "unmoderate"
    t.index ["blog_id", "blog_type"], name: "moderations_blog"
    t.index ["reportable_type", "reportable_id"], name: "moderations_reportable", unique: true
  end



create_table "posts", id: :serial, force: :cascade do |t|
    t.text "title", null: false
    t.text "body", null: false
    t.integer "feature_id", null: false
    t.integer "author_id"
    t.integer "scope_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.integer "post_votes_count", default: 0, null: false
    t.index ["body"], name: "post_body_search"
    t.index ["created_at"], name: "index_posts_on_created_at"
    t.index ["author_id"], name: "index_posts_on_author_id"
    t.index ["feature_id"], name: "index_posts_on_feature_id"
    t.index ["proposal_votes_count"], name: "index_posts_on_post_votes_count"
    t.index ["title"], name: "post_title_search"
  end
Run Code Online (Sandbox Code Playgroud)

aas*_*ish 28

要解决这个问题,我们必须告诉ActiveRecord查看表的顺序:

ActiveRecord::Base.connection.reset_pk_sequence!('table_name')
Run Code Online (Sandbox Code Playgroud)

现在ActiveRecord应该具有正确的序列值,并且应该能够正确地分配新的id.

解决错误

PG :: UniqueViolation:错误:重复键值违反唯一约束"moderations_reportable"DETAIL:键(reportable_type,reportable_id)=(Post,25)已存在.:INSERT INTO"moderations"("blog_id","reportable_type","reportable_id","created_at","updated_at","blog_type")VALUES($ 1,$ 2,$ 3,$ 4,$ 5,$ 6)返回"id"

"调节"表上发生错误.

rails console fix 运行以下命令

ActiveRecord::Base.connection.reset_pk_sequence!('moderations')
Run Code Online (Sandbox Code Playgroud)

谢谢

  • 是的,但是如果您再次弄乱它,则需要重置序列。 (2认同)

sea*_*vis 7

看起来您已向数据库添加了唯一索引:

t.index ["reportable_type", "reportable_id"], name: "moderations_reportable", unique: true
Run Code Online (Sandbox Code Playgroud)

使用唯一索引,您将只能拥有一个具有相同reportable_type和 的记录reportable_id。您很可能正在尝试为已经进行审核的可报告内容创建审核。


Ser*_*kij 6

修复所有数据库的pkey序列:

ActiveRecord::Base.connection.tables.each do |table_name| 
  ActiveRecord::Base.connection.reset_pk_sequence!(table_name)
end
Run Code Online (Sandbox Code Playgroud)