Ruby on rails Rails自动分配已经存在的id

Ruby on rails Rails自动分配已经存在的id,ruby-on-rails,ruby-on-rails-3,postgresql,Ruby On Rails,Ruby On Rails 3,Postgresql,我创建了一个新记录,如下所示: truck=truck.create(:name=>name,:user\u id=>2) 我的数据库目前有数千个卡车实体,但我将id分配给了其中几个实体,这样就留下了一些可用的id。所以,rails创建了id=150的项,并且工作正常。但随后它尝试创建一个项并将其id=151,但该id可能已经存在,因此我看到了这个错误: ActiveRecord::RecordNotUnique(PG::Error:Error:重复键值违反了唯一约束“companys\u pk

我创建了一个新记录,如下所示:

truck=truck.create(:name=>name,:user\u id=>2)

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

ActiveRecord::RecordNotUnique(PG::Error:Error:重复键值违反了唯一约束“companys\u pkey”
详细信息:密钥(id)=(151)已存在。

下一次我运行这个操作时,它只会分配ID152,如果这个值还没有被接受的话,它就可以正常工作。我如何让rails在分配id之前检查它是否已经存在

谢谢

编辑


卡车id是被复制的。用户已经存在,并且在本例中是一个常量。这实际上是一个遗留问题,我必须处理。一个选项是在让rails自动分配每个id时重新创建表。我开始认为这可能是最佳选择,因为我还有一些其他问题,但是迁移将非常复杂,因为Truck在许多其他表中都是外键。有没有一种简单的方法让rails使用Truck下已经存储的相同数据创建一个新表,并使用自动分配的ID和维护所有现有关系?

听起来像是数据库问题,而不是rails问题m、 您的数据库是否可能在您的
id
列上有一个不正确的标识种子?要测试,请尝试直接向数据库中插入几次,看看是否存在相同的行为。

Rails可能正在使用内置的PostgreSQL序列。序列的概念是只使用一次

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

SELECT setval('company_id_seq', (SELECT max(id) FROM company));
rails g task database correction_seq_id
我在猜测您的序列名“company_id_seq”、表名“company”和列名“id”…请用正确的名称替换它们。您可以使用
选择pg_get_serial_sequence('tablename','columname');
或使用
\d tablename
查看表定义


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

我这样做,解决了这个问题

ActiveRecord::Base.connection.tables.each do |t|
  ActiveRecord::Base.connection.reset_pk_sequence!(t)
end
我从这个线程中找到了reset\u pk\u序列。

基于@Apie

您可以创建任务并在需要时使用以下工具运行:

rake database:correction_seq_id
您可以创建如下任务:

SELECT setval('company_id_seq', (SELECT max(id) FROM company));
rails g task database correction_seq_id
并在生成的文件(
lib/tasks/database.rake
)中放入:


我按照命令解决了这个问题

在rails控制台中运行此命令

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

为什么不让rails自动分配ID?这将消除任何重复的危险?或者这是一个必须保留旧ID的遗留数据问题?只是想了解一下业务案例,因为在创建新对象时这不是正常的业务。@MBHNYC我认为D-Nice在创建时分配用户IDg公司,而不是你所想的身份证(我也做了一会儿).Ooo很好,抓住Anil-你完全正确。@D-Nice,也许可以将此表的迁移添加到你的帖子中,以防出现异常情况?试图编辑掉该用户id以消除混淆。不,抱歉,不清楚,公司id是被复制的。该用户已经存在,并且在本例中是一个常量。它实际上是一个我必须处理的遗留问题。将使用更多信息编辑帖子您不需要重新创建表。只需查看我的答案即可重置序列。为什么要进行向下投票?如果您将增量序列设置为低于其他现有值的值,因此插入时偶尔会发生冲突,则会发生这种情况正在处理数据。海报上已经说存在属于这种情况的现有数据。我可以很好地插入。在我出现此错误后,如果序列中的下一个id尚未使用,我实际上可以再次运行相同的操作并使其工作。似乎这是我的情况--我遇到了问题,但我插入的下一条记录工作正常,因此它必须将种子放在正确的位置。我猜这样做可以让自动分配从当前最高值+1开始吗?我认为这是我问题的最佳答案,但是,由于不相关的原因,我必须找到一种方法来使用我在评论中描述的策略。我不明白为什么会发生这种情况在with中?这发生在我身上,我想了解这是怎么可能的。@Websitescenes,如果在PostgreSQL中有一个串行列(串行列是其中默认值是序列中的下一个值的列),然后用该列中的硬值填充该表,序列将不会自动更新。例如:
创建表t(id序列非空主键);插入t值(1);插入t值(默认);错误:重复的键值违反唯一约束“t_pkey”详细信息:键(id)=(1)已经存在。
谢谢,这是最好的解决方案。在数据库传输之后,我也遇到了同样的问题。或者是一行等效的(用于rails控制台复制/粘贴的目的):
ActiveRecord::Base.connection.tables.each{t | ActiveRecord::Base.connection.reset_pk_sequence!(t)}
知道这是如何失去同步的吗?