2009-11-09 56 views
5

我正在現有的Rails站點上進行維護工作,並且遇到來自多對多關聯的一些問題。看起來這個網站最初是使用has_and_belongs_to_many爲幾個關係構建的,這些關係之後在業務邏輯中變得更加複雜,所以我需要使用has_many :through來支持關係表中的其他字段。但是,最初用於HABTM的連接表沒有主鍵,我必須添加一個以支持使用has_many :through進行單獨關係建模。Rails建模:將HABTM轉換爲has_many:通過

將主鍵添加到包含大量數據的現有表的最佳方式是什麼?有沒有另一種方法來做我想要的?

順便提一下,系統在Oracle上運行。

謝謝!

賈斯汀

UPDATE 09年11月9日15:58:我不是一個Oracle專家,在不爲空,自動遞增的甲骨文版本的荒野已經迷路,等等。最初我嘗試了Mike和Corey通過添加一個新字段作爲主鍵的建議,但Oracle不會讓我向非空表(ORA-01758)添加非空字段。然後我將數據導出爲SQL,刪除了行,添加了PK並將其設置爲非null,然後嘗試導入數據,但我一直收到「無法將NULL插入到ID ...」的錯誤(ORA-01400)。

最後,我嘗試使用Corey在他的評論中提出的遷移方法,但是當我手動更改數據庫時(「不能向非空表添加非空字段」),rake遇到了Oracle拋出的相同錯誤。我清理了表,運行了遷移(其工作),然後嘗試重新導入數據,但是我上次嘗試導入時出現了相同的錯誤(「無法將NULL插入到ID ...」)。如何保存我的數據並添加我需要的主鍵?我知道提出編寫耙子任務的可能性,但我不確定如何在這方面繼續前進。有任何想法嗎?

+0

另請參閱此最近的問題和答案:http://stackoverflow.com/questions/16159134/how-to-migrate-has-and-belongs-to-many-to-has-many-through/29067732# 29067732 – MZB 2015-03-16 00:02:37

回答

3

您需要創建新列,與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. 

取決於有多少行,在你的表可能需要同時填充序列值,但它會起作用。

6

我在管理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種子數據。

+0

感謝您的迴應,科裏。有沒有辦法爲所有先前存在的記錄自動填充id#? – justinbach 2009-11-09 18:26:09

+0

我不知道一個自動化的方式來做到這一點。我只是創建一個rake任務來遍歷它們並添加索引,但我比ruby更熟悉ruby。打開auto_increment會在您獲得現有數據集後添加id。 – coreypurcell 2009-11-09 18:41:49

1

使用alter table添加pk列。

編寫腳本以增量設置新的pk列值(某種循環)。

腳本完成後,再次使用alter table將列設置爲primary_key並自動遞增,將遞增開始值設置爲table_size + 1。