Rails自动分配已存在的id

时间:2012-06-17 03:54:06

标签: ruby-on-rails ruby-on-rails-3 postgresql

我创建了一条新记录:

truck = Truck.create(:name=>name, :user_id=>2)

我的数据库目前有几千个卡车实体,但是我将其中的一些ID分配给了其中一些实体,其中一些ID可用。所以正在发生的是rails创建id为150的项目并且它工作正常。但后来它尝试创建一个项目并为其指定id = 151,但该ID可能已经存在,所以我看到了这个错误:

ActiveRecord::RecordNotUnique (PG::Error: ERROR: duplicate key value violates unique constraint "companies_pkey" DETAIL: Key (id)=(151) already exists.

下次我运行动作时,它只会分配id 152,如果尚未使用该值,它将正常工作。如何在分配ID之前检查ID是否已存在?

谢谢!

修改

卡车ID是重复的内容。用户已经存在,在这种情况下是常量。它实际上是我必须处理的遗留问题。一种选择是在let rails重新创建表,这次自动分配每个id。我开始认为这可能是最好的选择,因为我还有其他一些问题,但是这样做的迁移会非常复杂,因为Truck是很多其他表中的外键。是否有一种简单的方法可以让rails创建一个新表,其中包含已存储在Truck下的相同数据,具有自动分配的ID并维护所有现有关系?

4 个答案:

答案 0 :(得分:196)

我这样做了解决了我的问题。

ActiveRecord::Base.connection.tables.each do |t|
  ActiveRecord::Base.connection.reset_pk_sequence!(t)
end

我找到了reset_pk_sequence!从这个线程。 http://www.ruby-forum.com/topic/64428

答案 1 :(得分:85)

Rails可能正在使用内置的PostgreSQL序列。序列的想法是它只使用一次。

最简单的解决方案是使用如下查询将company.id列的序列设置为表中的最高值:

SELECT setval('company_id_seq', (SELECT max(id) FROM company));

我猜测你的序列名称“company_id_seq”,表名“company”和列名“id”......请用正确的名称替换它们。您可以使用SELECT pg_get_serial_sequence('tablename', 'columname');获取序列名称,或使用\d tablename查看表格定义。

另一种解决方案是覆盖公司类中的save()方法,以便在保存之前手动设置新行的公司ID。

答案 2 :(得分:4)

听起来像数据库问题,而不是Rails问题。您的id列上的数据库是否有可能存在不正确的身份种子?要测试尝试直接在数据库中插入几个,并查看是否存在相同的行为。

答案 3 :(得分:0)

我通过以下命令解决了这个问题。

在Rails控制台中运行

ActiveRecord::Base.connection.reset_pk_sequence!('table_name')