简体   繁体   中英

How to change datatype of column with data

Let's say I have a table call_log that has a column named duration . Let's further pretend that when I put the table together, I made the mistake of making duration a varchar column instead of a number. Now I can't properly sort on that column. I want to rename the column so I issue...

ALTER TABLE call_log MODIFY (duration NUMBER);

But I get...

ORA-01439: column to be modified must be empty to change datatype.

My table has been in use and has data! And I don't want to lose the data. How do I modify the column's datatype without losing data?

Create a temporary column with the correct data type, copy the data to the new column, drop the old column, rename the new column to match what the old column was named.

ALTER TABLE call_log ADD (duration_temp NUMBER);
UPDATE call_log SET duration_temp = duration;
ALTER TABLE call_log DROP COLUMN duration;
ALTER TABLE call_log RENAME COLUMN duration_temp TO duration;

The idea for this answer came from Oracle's forums .

the previous solution is excellent, however if you don't want to change the columns orders in call_log table structure, then the following steps are for this:

create table temp_call_log  as select * from call_log; /* temp backup table for call_log */
UPDATE call_log SET duration = null;
/*check,... be sure.... then commit*/
commit;
ALTER TABLE call_log MODIFY duration NUMBER;
UPDATE call_log c SET c.duration = (select t.duration from temp_call_log t where t.primarykey_comumn = c.primarykey_column);
/*check,... be sure.... then commit*/
commit;
drop table temp_call_log;

note1: change primarykey_comumn with primary key in table call_log.

note2: this solution assumes that your data size is not big.

The best solution to preserve the original order of columns: create a temp column, copy the data to it, set the original column to null, modify its type, set the data from temp column back to it and drop the temp column:

ALTER TABLE call_log ADD duration_temp NUMBER;
UPDATE call_log SET duration_temp = duration;
UPDATE call_log SET duration = NULL;
ALTER TABLE call_log MODIFY duration NUMBER;
UPDATE call_log SET duration = duration_temp;
ALTER TABLE call_log DROP (duration_temp);

or some constrains, I could not use the first two solutions:

CREATE TABLE call_log_temp AS (SELECT * FROM call_log where rownum = 0);
ALTER TABLE call_log_temp MODIFY duration NUMBER;
INSERT INTO call_log_temp( id, duration, and_all_other_columns, ... )
  SELECT id, duration, and_all_other_columns, ...
  FROM call_log;  
DROP TABLE call_log;    
ALTER TABLE call_log_temp RENAME TO call_log;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM