从Rails控制台修改数据库ID?

16

我有一个小型数据库,并通过Rails页面添加条目。 我“销毁”了其中一个条目,现在我的ID序列跳过一条记录。例如,我现在有42和44,而不是显而易见的42、43、44。

我想知道是否有一种方法可以通过控制台编辑新对象的ID号码。我已经尝试过:

record.id = 43
record.save

record = record.new
record.attributes = { :id => 43 }

但两者都没有起作用。我相当确定必须有一种控制台方法可以实现这一点,但我似乎在谷歌上找不到太多具体信息,而且我可能读错了Rails API...难道我可能需要通过SQLite中的直接SQL来完成这个操作吗?

谢谢。

3个回答

40

最好的做法是直接执行SQL,并解决序列中的时间问题。

尝试访问控制台(ruby script/console)并键入:

>> sql = "update records set id=43 where id=44"
>> ActiveRecord::Base.connection.execute(sql)

44是新创建对象的ID,43则是你表格中缺失的ID。

祝你好运!


1
我同意更改ID是一个坏主意,但当你需要将数据恢复到生产数据库中时,比如说,当你“丢失”了一些记录时,这是完美的。 - Matt Darby
很好的跳出框架的思维。 - RonanOD

23

实际上,你可以手动为新对象设置id:

record = Record.new
record.id = 1234
record.save

然而,你试图更新一个已存在对象的id。当你设置record.id = 43并调用save时,ActiveRecord会尝试生成如下SQL语句:

update records set id = 43 where id = 43

注意,它要更新的id与你尝试更改的id相同。这就是为什么它不起作用的原因。

所以是的,你需要使用SQL来更改它。是否这是个好主意是另一个问题,但有时需要这样做。


1
很棒的解决方案,我希望我能投两票让它排到最前面。我喜欢那些解释问题的解决方案。我已经找到了这个实现规范化“枚举”的用途。例如,一个用户可能有多个角色,但是这些角色在部署中将保持一致,因此我使用rake任务添加它们。硬编码它们的ID确保它们在我的本地机器和服务器上相同。这可能有点挑剔,也可能永远不需要,但这让我稍微放心了一点 :) - Jaime Bellmyer

4
我是否需要通过sqlite中的直接SQL来完成这个操作?
是的。
ActiveRecord的全部意义在于它抽象了DB函数并返回数据集合。你不应该担心记录的ID,这是特定于DB的东西。我想不出任何原因去引用模型的ID。
如果您的应用程序依赖于具有序列号,则应向模型添加另一个具有此序列号的字段。例如,如果我有一个带有产品的商店(Product模型),并且我将ID编号提供给其他供应商。两周后,我的老板要求我为两种产品变体分别提供唯一但相似的ID:“45a”和“45b”。糟糕。ID字段应仅由数据库和ActiveRecord用于识别记录,而不是您或您的用户。
可能会有一种偏僻的方法可以强制设置ID(如果DB允许),但这种方法很少见。不要试图找到它:)
话虽如此,输入ruby script/dbconsole可以快速打开sqlite界面,而无需输入密码。
此外,如果您删除sqlite数据库,将重置计数器并从0开始。伟大的力量带来伟大的责任。
编辑
如果我没记错,Dave Thomas在某个地方写过这个问题。也许这里

1
这是一个非常讽刺和没有帮助的评论。不值得标记,但值得修改。 - ivanreese

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接