Oracle: как удалить подраздел определенного раздела
Я использую таблицу oracle 11 с разделением интервалов и разделением списка, как это (упрощено):
CREATE TABLE LOG
(
ID NUMBER(15, 0) NOT NULL PRIMARY KEY
, MSG_TIME DATE NOT NULL
, MSG_NR VARCHAR2(16 BYTE)
) PARTITION BY RANGE (MSG_TIME) INTERVAL (NUMTOYMINTERVAL (1,'MONTH'))
SUBPARTITION BY LIST (MSG_NR)
SUBPARTITION TEMPLATE (
SUBPARTITION login VALUES ('FOO')
, SUBPARTITION others VALUES (DEFAULT)
)
(PARTITION oldvalues VALUES LESS THAN (TO_DATE('01-01-2010','DD-MM-YYYY')));
Как отбросить конкретный подпункт в течение определенного месяца, не зная (сгенерированное системой) имя этого подпункта? Существует синтаксис " alter table ... drop subpartition for (subpartition_key_value,...)" но я не вижу способа указать месяц, для которого я удаляю подпункт. The администрирование раздела руководство также не приводит никаких примеров. 8-}
3 ответов
вы можете использовать таблицы метаданных, чтобы получить конкретное имя подраздела:
SQL> insert into log values (1, sysdate, 'FOO');
1 row(s) inserted.
SQL> SELECT p.partition_name, s.subpartition_name, p.high_value, s.high_value
2 FROM user_tab_partitions p
3 JOIN
4 user_tab_subpartitions s
5 ON s.table_name = p.table_name
6 AND s.partition_name = p.partition_name
7 AND p.table_name = 'LOG';
PARTITION_NAME SUBPARTITION_NAME HIGH_VALUE HIGH_VALUE
--------------- ------------------ ------------ ----------
OLDVALUES OLDVALUES_OTHERS 2010-01-01 DEFAULT
OLDVALUES OLDVALUES_LOGIN 2010-01-01 'FOO'
SYS_P469754 SYS_SUBP469753 2012-10-01 DEFAULT
SYS_P469754 SYS_SUBP469752 2012-10-01 'FOO'
SQL> alter table log drop subpartition SYS_SUBP469752;
Table altered.
если вы хотите динамически удалить раздел, может быть сложно найти его с помощью ALL_TAB_SUBPARTITIONS
посмотреть потому что HIGH_VALUE
столбец может быть непростым для запроса. В этом случае вы можете использовать DBMS_ROWID
чтобы найти подпункт object_id
из данной строки:
SQL> insert into log values (4, sysdate, 'FOO');
1 row(s) inserted.
SQL> DECLARE
2 l_rowid_in ROWID;
3 l_rowid_type NUMBER;
4 l_object_number NUMBER;
5 l_relative_fno NUMBER;
6 l_block_number NUMBER;
7 l_row_number NUMBER;
8 BEGIN
9 SELECT rowid INTO l_rowid_in FROM log WHERE id = 4;
10 dbms_rowid.rowid_info(rowid_in =>l_rowid_in ,
11 rowid_type =>l_rowid_type ,
12 object_number =>l_object_number,
13 relative_fno =>l_relative_fno ,
14 block_number =>l_block_number ,
15 row_number =>l_row_number );
16 dbms_output.put_line('object_number ='||l_object_number);
17 END;
18 /
object_number =15838049
SQL> select object_name, subobject_name, object_type
2 from all_objects where object_id = '15838049';
OBJECT_NAME SUBOBJECT_NAME OBJECT_TYPE
--------------- --------------- ------------------
LOG SYS_SUBP469757 TABLE SUBPARTITION
как оказалось, синтаксис "subpartition for" действительно работает, хотя это, похоже, секретный Оракул не хочет вам рассказывать. :-)
ALTER TABLE TB_LOG_MESSAGE DROP SUBPARTITION FOR
(TO_DATE('01.02.2010','DD.MM.YYYY'), 'FOO')
это удаляет подраздел, который будет содержать MSG_TIME 2010/02/01 и MSG_NR FOO. (Не обязательно, что существует фактическая строка с этим точным MSG_TIME и MSG_NR. Однако он выдает ошибку, если такого подпункта нет.)
Спасибо за пост - было очень полезно для меня.
одно замечание, хотя на приведенном выше скрипте, чтобы идентифицировать раздел и удалить его:
на object_id
возвращено dbms_rowid.rowid_info
не object_id
на all_objects
таблица. Это на самом деле data_object_id
. Отмечается, что обычно эти идентификаторы совпадают. Однако после усечения секционированной таблицы несколько раз эти идентификаторы расходились в моей базе данных. Следовательно, было бы разумно вместо этого использовать data_object_id
чтобы выяснить, название раздела:
select object_name, subobject_name, object_type
from all_objects where data_object_id = '15838049';
From the table description of ALL_OBJECTS:
OBJECT_ID номер объекта объекта DATA_OBJECT_ID номер объекта сегмента, который содержит объект
http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_rowid.htm
в примере кода, приведенном в приведенной выше ссылке,DBMS_ROWID.ROWID_OBJECT(row_id)
вместо этого используется для получения той же информации, что и dbms_rowid.rowid_info
. Однако в документации по этому образцу упоминается, что это объект данных номер из ROWID.
примеры
этот пример возвращает ROWID для строки в таблице EMP, извлекает номер объекта данных из ROWID с помощью функции ROWID_OBJECT в пакете DBMS_ROWID отображается номер объекта:
объявить OBJECT_NO целое число; row_id ROWID; ... Начать
Выберите ROWID в row_id из emp Где empno = 7499; object_no: = DBMS_ROWID.ROWID_OBJECT(row_id); DBMS_OUTPUT.PUT_LINE('объект. # есть '//object_no);...