我正在使用带有区间分区的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 , ...)"但我没有看到指定删除子分区的月份的方法。 partition administration guide也没有给出任何例子。 8 - }
答案 0 :(得分: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
答案 1 :(得分:3)
事实证明,“subpartition for”语法确实有效,尽管这似乎是Oracle不想告诉你的秘密。 : - )
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的实际行。但是,如果没有这样的子分区,则会抛出错误。)
答案 2 :(得分:1)
感谢帖子 - 这对我来说非常有用。
虽然在上面的脚本中有一个观察来识别分区并将其删除:
object_id
返回的dbms_rowid.rowid_info
不是object_id
表的all_objects
。它实际上是data_object_id
。据观察,通常这些ID匹配。但是,在多次截断分区表后,这些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的数据对象编号。
实施例
此示例返回EMP表中行的ROWID,extract 使用ROWID_OBJECT函数从ROWID获取数据对象编号 在DBMS_ROWID包中,然后显示对象编号:
DECLARE object_no INTEGER; row_id ROWID; ......开始 SELECT ROWID INTO row_id FROM emp WHERE empno = 7499; object_no:= DBMS_ROWID.ROWID_OBJECT(row_id); DBMS_OUTPUT.PUT_LINE('对象#是 “|| object_no); ...