2009-11-09 7 views
5

Sto eseguendo lavori di manutenzione su un sito di Rails esistente e sto riscontrando alcuni problemi derivanti da associazioni many-to-many. Sembra che il sito sia stato inizialmente creato usando has_and_belongs_to_many per alcune relazioni che sono diventate più complicate nella logica di business, quindi ho bisogno di usare has_many :through per supportare campi aggiuntivi nella tabella delle relazioni. Tuttavia, la tabella di join inizialmente utilizzata per HABTM non ha una chiave primaria e devo aggiungerne una per supportare la modellazione di relazioni separate utilizzando has_many :through.Modellazione di rails: conversione di HABTM in has_many: tramite

Qual è il modo migliore per aggiungere una chiave primaria a una tabella esistente con molti dati? C'è un altro modo per fare ciò che sto cercando?

Per inciso, il sistema è in esecuzione su Oracle.

Grazie!

Justin

UPDATE 11/9/09 15:58: Io non sono un esperto di Oracle e sono stato perdersi nella natura selvaggia delle versioni di Oracle di non nullo, incremento automatico, e così via. Inizialmente ho provato a fare ciò che Mike e Corey raccomandavano aggiungendo un nuovo campo come chiave primaria, ma Oracle non mi permetteva di aggiungere un campo non nullo a una tabella non vuota (ORA-01758). Poi ho esportato i dati come SQL, ho abbandonato le righe, ho aggiunto il PK e l'ho impostato come non-null, poi ho cercato di importare i dati, ma ho continuato a ricevere errori con la frase "non posso inserire NULL in id ..." (ORA-01400).

Infine, ho provato a utilizzare una migrazione come suggerisce Corey nel suo commento, ma il rake ha colpito gli stessi errori che Oracle stava generando quando ho modificato manualmente il database ("non è possibile aggiungere un campo non null alla tabella non vuota"). Ho eliminato la tabella, eseguito la migrazione (che ha funzionato) e ho tentato di reimportare i dati, ma ho ricevuto gli stessi errori l'ultima volta che ho provato a importare ("impossibile inserire NULL in id ..."). Come posso salvare i miei dati e aggiungere le chiavi primarie di cui ho bisogno? So che la possibilità di scrivere un rake è stata suggerita, ma non sono sicuro su come procedere su questo fronte. Qualche idea?

+0

Vedere anche questa domanda e le risposte più recenti: http://stackoverflow.com/questions/16159134/how-to-migrate-has-and-belongs-to-many-to-has-many-through/29067732# 29067732 – MZB

risposta

3

È necessario creare la nuova colonna, riempire con i valori PK e quindi creare un PK sulla nuova colonna, ad esempio:

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. 

A seconda di quante righe sono nella tabella si può prendere un mentre per popolare i valori della sequenza, ma funzionerà.

6

Io uso SQL Developer durante l'amministrazione di un database Oracle. Basta creare la colonna e aggiungere un vincolo al database, ad esempio:

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

magari vedere here per un po 'più in dettaglio.

Edit:

Ora che ripenso questo si dovrebbe essere in grado di farlo in una migrazione

add_column :table, :id, :primary_key 

È quindi necessario seminare alcuni dati all'interno della migrazione. Solo codice rubino che scorre e aggiunge il tuo indice. Vedi seed_fu e db-populate per aiuto. Rails 3 ti permetterà di seminare dati con rake db: seed.

+0

Grazie per la risposta, Corey. C'è un modo per autopopolare l'id # per tutti i record preesistenti? – justinbach

+0

Non conosco un modo automatico per farlo. Vorrei solo creare un rake task che itera su di loro e aggiunge l'indice, ma ho più familiarità con Ruby di SQL. L'attivazione di auto_increment aggiungerà gli ID dopo aver ottenuto il set di dati esistente. – coreypurcell

1

Utilizzare alter tabella per aggiungere la colonna pk.

Scrivere uno script per impostare i nuovi valori della colonna pk in modo incrementale (una sorta di ciclo).

Una volta terminato lo script, utilizzare di nuovo alter table per impostare la colonna su primary_key e auto-increment, impostando il valore iniziale dell'incremento su table_size + 1.