Как преобразовать секционированную таблицу в обычную?
В целях эксперимента привели обычную таблицу к секционированной путем выполнения alter table modify ... с интервальным партиционированием и статическими сабпартициями.
Существует ли метод вернуть ее в обратное состояние?
Просто не хочется восстанавливать DDL и копировать данные (долго и ресурсы требуются).
Ответы (2 шт):
У команды ALTER TABLE, обратного аналога клаузы modify_to_partitioned нет.
Одна из возможных алтернатив -- экспорт/импорт с опцией PARTITION_OPTIONS=merge.
Пример таблицы:
create table t1 (id int primary key, memo varchar2(16), created date)
partition by range (created) (
partition t1_part_2020 values less than (date'2021-01-01'),
partition t1_part_2021 values less than (maxvalue))
/
insert into t1
select rownum, 'memo row '||rownum, date'2020-01-01'+(rownum-1)
from dual connect by level<=999
/
commit;
select table_name, partitioned
from user_tables where table_name='T1'
/
TABLE_NAME PARTITIONED
---------- ------------
T1 YES
Экспорт ничем не отличается, после таблицу надо удалить (не забудте про бэкап!!!):
$ expdp me/me@dbsrv/pdb1 directory=data_pump_dir tables=t1 dumpfile=t1.dmp logfile=exp.log
[...]
. . exported "ME"."T1":"T1_PART_2020" 16.05 KB 366 rows
. . exported "ME"."T1":"T1_PART_2021" 23.81 KB 633 rows
Master table "ME"."SYS_EXPORT_TABLE_01" successfully loaded/unloaded
******************************************************************************
SQL> drop table t1 cascade constraints purge;
Импорт с опцией для объединения партиций:
$ impdp me/me@dbsrv/pdb1 directory=data_pump_dir partition_options=merge \
dumpfile=t1.dmp logfile=imp.log
Processing object type TABLE_EXPORT/TABLE/TABLE_DATA
. . imported "ME"."T1":"T1_PART_2021" 23.81 KB 633 rows
. . imported "ME"."T1":"T1_PART_2020" 16.05 KB 366 rows
select table_name, partitioned
from user_tables where table_name='T1'
/
TABLE_NAME PARTITIONED
---------- ------------
T1 NO
Другое решение -- реорганизовать таблицу онлайн помощью пакета DBMS_REDEFINITION, что позволит сократить время её недоступности (downtime) до нескольких минут.
Для этого, проверятся возможность реорганизации таблицы и создаётся внутренняя тблица со структурой целевой таблицы, в нашем случае без партиций:
exec sys.dbms_redefinition.can_redef_table (uname => 'db', tname => 't1')
create table intert1 (id int primary key, memo varchar2(16), created date)
/
Следуюшие шаги включают: запуск реорганизации, копирование всех зависимых объектов, контроль ошибок и, опционально, синхронизацию таблиц:
begin
dbms_redefinition.start_redef_table (
uname => 'me',
orig_table => 't1',
int_table => 'intert1');
end;
/
declare
numerr pls_integer;
begin
dbms_redefinition.copy_table_dependents (
uname => 'me',
orig_table => 't1',
int_table => 'intert1',
copy_indexes => dbms_redefinition.cons_orig_params,
copy_triggers => true,
copy_constraints => true,
copy_privileges => true,
ignore_errors => true,
num_errors => numerr);
dbms_output.put_line ('errors='||numerr);
end;
/
select object_name, base_table_name, ddl_txt
from dba_redefinition_errors;
exec dbms_redefinition.sync_interim_table ( -
uname => 'me', orig_table => 't1', int_table => 'intert1');
При завершении реорганизации целевая таблица будет заблокирована на несколько минут. Затем, она полностью соответствует по структуре внутренней таблице, и последняя может быть удалена:
exec dbms_redefinition.finish_redef_table ( -
uname => 'me', orig_table => 't1', int_table => 'intert1');
select table_name, partitioned
from user_tables where table_name='T1';
TABLE_NAME PARTITIONED
---------- ------------
T1 NO
drop table intert1 purge;