Как изменить тип данных столбца если таблица заполнена и используется?

Есть столбец ID с числовыми значениями. При создании таблицы, в следствии ошибки проектирования, он был объявлен как VARCHAR.

С этим столбцом постоянно возникают проблемы, например, сравнение значений столбца может привести к неожидаемым результатам:

select to_number (max (id)) maxid from ( 
    select '9' id from dual union all 
    select '10'   from dual);

     MAXID
----------
         9 

Есть решение - изменить тип данных столбца:

alter table table1 modify id number(10,0);

, но оно выдает ошибку:

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

Какой наилучший метод решения этой проблемы?


Ответы (1 шт):

Автор решения: 0xdb

Можно реорганизовать таблицу во время её использования с помощью PL/SQL пакета DBMS_REDEFINITION.

Воспроизводимый пример:

create table t1 (
    id varchar2 (10) primary key);
create table t2 (
    id number(10,0) primary key);

insert into t1 
    select '9'  from dual union all 
    select '10' from dual;    
commit;

begin 
    dbms_redefinition.start_redef_table ( 
        uname=>user, orig_table=>'t1', 
        int_table=>'t2', 
        col_mapping  => 'to_number (id) id', 
        options_flag => dbms_redefinition.cons_use_rowid);
end;
/
exec dbms_redefinition.sync_interim_table (user, 't1', 't2');

При завершении реорганизации, таблица t1 будет кратковременно заблокирована, а затем она полностью соответствует по структуре таблице t2, и последняя может быть удалена:

exec dbms_redefinition.finish_redef_table (user, 't1', 't2');

desc t1

Name Null?    Type       
---- -------- ---------- 
ID   NOT NULL NUMBER(10) 

select max (id) maxid from t1;

     MAXID
----------
        10

drop table t2 cascade constraints purge;
→ Ссылка