ORA-14097: несоответствие типа или размера столбца в ALTER TABLE EXCHANGE PARTITION

Я столкнулся с ORA-14097 при обмене разделами. Может ли кто-нибудь поделиться со мной светом?

У меня есть следующая таблица source_tbl (неразделенная), и я намереваюсь разделить ее с помощью столбца VALID_PERIOD_END.

CREATE TABLE source_tbl
   (    INVOICE_ID NUMBER(15,0) NOT NULL ENABLE, 
    LATEST_FLAG_NAME VARCHAR2(3000), 
    STD_HASH **RAW**(1000), 
    VALID_PERIOD_START TIMESTAMP (6), 
    VALID_PERIOD_END **TIMESTAMP** (6), 
    OVERSEAS NUMBER, 
   .. <another 20 number columns)
    VIP_NO NUMBER
   ) partition by range(VALID_PERIOD_END)
nologging;

Теперь в этой таблице 5 миллионов строк, и я хочу разбить ее на VALID_PERIOD_END, чтобы, если это «9999-12-31 23:59:59» (текущий), он находился в одном разделе, а остальные в другом разделе.

Я создал вторую таблицу с именем TEMP_tbl.

CREATE TABLE TEMP_tbl
   (    INVOICE_ID NUMBER(15,0) NOT NULL ENABLE, 
    LATEST_FLAG_NAME VARCHAR2(3000), 
    STD_HASH **RAW**(1000), 
    VALID_PERIOD_START TIMESTAMP (6), 
    VALID_PERIOD_END **TIMESTAMP** (6), 
    OVERSEAS NUMBER, 
   .. <another 20 number columns)
    VIP_NO NUMBER
   )partition by range(VALID_PERIOD_END)
(partition p1 values less than(maxvalue)) nologging;

TEMP_tbl имеет точно такую ​​же структуру данных, что и source_tbl, поскольку сценарий был запущен с использованием dbms_metadata.get_ddl.

Я выполнил сбор статуса таблицы без каких-либо ошибок

EXEC DBMS_STATS.gather_table_stats(USER, upper('source_tbl'), cascade => TRUE);

Однако, когда я пытаюсь выполнить следующий оператор раздела обмена, у меня возникает ошибка выше

alter table TEMP_tbl
          exchange partition p1
          with table source_tbl
          without validation
          update global indexes
;

Я проверил user_tab_cols и подтверждаю, что в source_tbl нет скрытого столбца. Будет ли это из-за необработанного столбца из моей таблицы?

Заранее спасибо!


person E Leung    schedule 28.07.2021    source источник
comment
Есть еще вопрос по похожей теме. Это не совсем дубликат, но он может быть полезен: stackoverflow.com/questions/41684333/   -  person Del    schedule 28.07.2021
comment
@Del, Да, я заметил это и попробовал инструкцию из ответа. Однако у меня нет скрытого столбца. Вот почему я поднял блог.   -  person E Leung    schedule 28.07.2021
comment
Я вижу примечание в онлайн-документации о перемещении таблицы со столбцом LONG RAW, но ничего о RAW или об обмене разделами с этими типами данных.   -  person Del    schedule 28.07.2021
comment
В качестве альтернативного подхода вы можете рассмотреть пакет dbms_redefinition для добавить секционирование к существующей таблице. Он также сам обрабатывает необходимые зависимости.   -  person astentx    schedule 28.07.2021
comment
Являются ли те sql, которые вы на самом деле (помимо ***)? потому что ваш код для source_tbl говорит «разделить по диапазону..»   -  person gsalem    schedule 28.07.2021


Ответы (1)


В Oracle 12.2 представлены две новые функции секционирования, которые отлично помогут вам в этом.

  1. Был введен новый ALTER TABLE MODIFY PARTITION BY DDL, который позволяет преобразовывать неразделенную таблицу в многораздельную. Эта операция скопирует данные из существующей неразделенной таблицы в новые разделы таблицы, поэтому она может выполняться долго. Вы можете указать ключевое слово ONLINE для выполнения операции в онлайн-режиме, что означает, что операции DML над таблицей будут разрешены во время работы ALTER TABLE. Например:
    ALTER TABLE source_tbl
      MODIFY PARTITION BY RANGE(VALID_PERIOD_END)
      (partition p1 values less than (timestamp '9999-12-31 23:59:59'),
       partition p2 values less than (maxvalue))
      ONLINE;
  1. Чтобы помочь в решении EXCHANGE PARTITION проблем, с которыми вы сталкиваетесь, предложение FOR EXCHANGE WITH TABLE было введено в CREATE TABLE. Это специально предназначено для точного сопоставления физических столбцов при создании новой таблицы, которая будет заменена существующей таблицей. Дополнительно можно использовать FOR EXCHANGE WITH TABLE вместе с PARTITION BY для создания секционированной таблицы, которой можно обмениваться с исходной таблицей. Например:
    CREATE TABLE TEMP_tbl
      PARTITION BY RANGE(VALID_PERIOD_END)
      (partition p1 values less than(maxvalue))
      FOR EXCHANGE WITH TABLE source_tbl;

Вот статья в блоге, в котором описываются оба этих улучшения разделения. И вот еще одна статья в блоге, в которой конкретно рассказывается об использовании CREATE TABLE ... FOR EXCHANGE WITH TABLE для устранения EXCHANGE PARTITION ошибок.

Вы не указали, какую версию Oracle вы используете, поэтому, возможно, вы все еще используете 11g. В этом случае вам, вероятно, нужно углубиться в USER_TAB_COLS, чтобы увидеть разницу между двумя таблицами. Вы упомянули, что уже проверили наличие скрытых столбцов (что хорошо), но могут возникнуть и другие несоответствия.

Следует иметь в виду, что атрибуты столбца NULLABLE должны совпадать между двумя таблицами. Если в одной таблице есть ограничение первичного ключа, а в другой нет, столбец может быть ненулевым в таблице с первичным ключом и нулевым в другой таблице, что вызовет ORA-14097.

Если это не объясняет проблему, вы также можете проверить порядок SEGMENT_COLUMN_ID, DATA_TYPE, DATA_LENGTH, DATA_PRECISION и DATA_PRECISION. Поскольку вы использовали dbms_metadata.get_ddl для создания своей таблицы, эти вещи должны совпадать, но должна быть какая-то разница, иначе вы не получите ошибку.

Столбец RAW(1000) не должен быть проблемой для EXCHANGE PARTITION.

person George Eadon    schedule 28.07.2021