【问题标题】:Rails modeling: converting HABTM to has_many :throughRails 建模:将 HABTM 转换为 has_many :through
【发布时间】:2010-12-14 17:14:17
【问题描述】:

我正在对现有的 Rails 站点进行维护工作,并且遇到了一些源自多对多关联的问题。看起来该站点最初是使用 has_and_belongs_to_many 构建的一些关系,这些关系后来在业务逻辑中变得更加复杂,所以我需要使用 has_many :through 来支持关系表中的其他字段。但是,最初用于 HABTM 的连接表没有主键,我必须添加一个以支持使用 has_many :through 的单独关系建模。

向包含大量数据的现有表添加主键的最佳方法是什么?还有另一种方法可以做我想做的事情吗?

顺便说一下,系统是在 Oracle 上运行的。

谢谢!

贾斯汀

更新 2009 年 11 月 9 日下午 3:58:我不是 Oracle 专家,并且一直迷失在 Oracle 的非空、自动增量等版本的荒野中。最初,我尝试按照 Mike 和 Corey 的建议添加一个新字段作为主键,但 Oracle 不允许我将非空字段添加到非空表 (ORA-01758)。然后我将数据导出为 SQL,删除行,添加 PK 并将其设置为非空,然后尝试导入数据,但我不断收到错误消息“无法将 NULL 插入 id...” (ORA-01400)。

最后,我尝试使用 Corey 在他的评论中建议的迁移,但 rake 遇到了当我手动更改数据库时 Oracle 抛出的相同错误(“无法将非空字段添加到非空表”)。我清除了表格,运行了迁移(有效),然后尝试重新导入数据,但我上次尝试导入时遇到了相同的错误(“无法将 NULL 插入 id ...”)。如何保存我的数据并添加我需要的主键?我知道有人提出了编写 rake 任务的可能性,但我不确定如何在这方面进行。有什么想法吗?

【问题讨论】:

标签: ruby-on-rails oracle primary-key data-modeling ora-01400


【解决方案1】:

我在管理 oracle 数据库时使用SQL Developer。只需创建列并向数据库添加约束,例如:

sql> alter table Employee add constraint Employee_pk primary key(Employee_ID);

更多详情请查看here

编辑:

现在我重新考虑这一点,您应该能够在迁移中做到这一点

add_column :table, :id, :primary_key

然后,您需要在迁移中植入一些数据。只是遍历并添加索引的 ruby​​ 代码。请参阅 seed_fudb-populate 寻求帮助。 Rails 3 将允许您使用 rake db:seed 播种数据。

【讨论】:

  • 感谢科里的回复。有没有办法为所有预先存在的记录自动填充 id #'s?
  • 我不知道自动化的方法。我只会创建一个遍历它们并添加索引的 rake 任务,但我对 ruby​​ 比对 SQL 更熟悉。开启 auto_increment 会在你获取现有数据集后添加 id。
【解决方案2】:

您需要创建新列,用 PK 值填充它,然后在新列上创建一个 PK,例如:

SQL> create table no_pk_tab (c1 varchar2(10), c2 varchar2(10))
Table created.
SQL> insert into no_pk_tab values ('one', 'one')
1 row created.
SQL> insert into no_pk_tab values ('two', 'two')
1 row created.

SQL> alter table no_pk_tab add (id integer)
Table altered.

SQL> create sequence no_pk_seq
start with 1
increment by 1
Sequence created.

SQL> update no_pk_tab set id = no_pk_seq.nextval
2 rows updated.
SQL> select * from no_pk

C1         C2             PK_COL
---------- ---------- ----------
one        one                 1
two        two                 2

2 rows selected.

SQL> alter table no_pk add primary key (pk_col) using index
Table altered.

根据表中有多少行,填充序列值可能需要一段时间,但它会起作用。

【讨论】:

    【解决方案3】:

    使用alter table添加pk列。

    编写脚本以增量方式设置新的 pk 列值(某种循环)。

    脚本完成后,再次使用 alter table 将列设置为 primary_key 并自动递增,将递增起始值设置为 table_size + 1。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-04
      • 2014-09-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-06
      • 1970-01-01
      相关资源
      最近更新 更多