2012-09-11 116 views
6

我使用與間隔分區和列表子分區這樣一個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'))); 

如何刪除特定subpartitition特定月不知道子系統的(系統生成的)名稱?有一個語法"alter table ... drop subpartition for (subpartition_key_value , ...)",但我沒有看到一種方法來指定我刪除子分區的月份。 partition administration guide也沒有給出任何例子。 8}

回答

3

事實證明,語法確實工作的「子分區」,儘管這似乎是一個祕密甲骨文並不希望告訴你。 :-)

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實際的行,但如果沒有這樣的子分區,則會引發錯誤。)

+3

如果你谷歌的「drop subpartition for」,你實際上會找到一個涵蓋該語法的專利申請。 8 {{}軟件專利會變得更加邪惡嗎? http://www.patentstorm.us/applications/20080313133/description.html –

+0

它於2013年發佈http://www.google.com/patents/US8356014(新鏈接,因爲我在hstoerr的鏈接中看不到任何內容) – jmsu

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

感謝帖子 - 它對我非常有用。雖然在上面的腳本

一個觀察來確定分區,並將其刪除:

的由dbms_rowid.rowid_info返回object_id不是all_objectsobject_id。它實際上是data_object_id。據觀察,通常這些ID匹配。但是,在多次截斷分區表之後,這些ID在我的數據庫中發散。因此,它可能是合理的,而不是使用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對象數量

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,提取 從ROWID數據對象數,使用ROWID_OBJECT功能 在DBMS_ROWID包,然後顯示對象數:

DECLARE object_no INTEGER; row_id ROWID; ...BEGIN
SELECT ROWID INTO row_id FROM emp WHERE empno = 7499; object_no:= DBMS_ROWID.ROWID_OBJECT(row_id); DBMS_OUTPUT.PUT_LINE('The obj。#is '|| object_no); ...