假设我有一个表call_log
,其中有一个名为duration
的列。让我们进一步假装当我把表放在一起时,我错误地将duration
变为varchar列而不是数字。现在我无法正确排序该列。我想重命名列,以便发出...
ALTER TABLE call_log MODIFY (duration NUMBER);
但我明白了......
ORA-01439: column to be modified must be empty to change datatype.
我的桌子一直在使用并且有数据!而且我不想丢失数据。如何在不丢失数据的情况下修改列的数据类型?
答案 0 :(得分:12)
使用正确的数据类型创建临时列,将数据复制到新列,删除旧列,重命名新列以匹配旧列的命名。
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;
这个答案的想法来自Oracle's forums。
答案 1 :(得分:2)
之前的解决方案非常好,但是如果您不想更改call_log表结构中的列顺序,那么以下步骤适用于此:
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:使用表call_log中的主键更改primarykey_comumn。
note2:此解决方案假设您的数据量不大。
答案 2 :(得分:2)
保留列原始顺序的最佳解决方案:创建一个临时列,将数据复制到该列,将原始列设置为null,修改其类型,将数据从temp列设置回该列,然后删除temp列:
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);
答案 3 :(得分:0)
或某些约束,我无法使用前两种解决方案:
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;