2012-09-11 27 views
6

estoy usando una tabla de Oracle 11 con la partición de intervalos y lista subparticiones como esto (simplificado):Oracle: cómo colocar un subpartición de una partición específica

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'))); 

¿Cómo se me cae un subpartitition específico para una determinada mes sin conocer el nombre (generado por el sistema) de la subpartición? Hay una sintaxis "alter table ... drop subpartition for (subpartition_key_value , ...)" pero no veo una forma de especificar el mes para el que estoy eliminando la subpartición. El partition administration guide tampoco da ningún ejemplo. 8-}

Respuesta

3

Como resultado, el "subpartición para" sintaxis trabaja de hecho, a pesar de que parece ser un Oracle secreto no quiere para contarte sobre. :-)

ALTER TABLE TB_LOG_MESSAGE DROP SUBPARTITION FOR 
     (TO_DATE('01.02.2010','DD.MM.YYYY'), 'FOO') 

Esto borra la subpartición que contendría MSG_TIME 2010/02/01 y MSG_NR FOO. (No es necesario que haya una fila real con este MSG_TIME y MSG_NR exactos. Sin embargo, arroja un error si no existe tal subpartición)

+3

Si buscas en Google para "soltar la subpartición para" en realidad encuentras una solicitud de patente que cubre esa sintaxis. 8- {} ¿Las patentes de software se vuelven aún más malvadas? http://www.patentstorm.us/applications/20080313133/description.html –

+0

Se publicó en 2013 http://www.google.com/patents/US8356014 (nuevo enlace ya que no puedo ver nada en el enlace de hstoerr) – jmsu

3

Puede utilizar las tablas de metadatos para obtener el nombre subpartición específica:

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. 

Si desea colocar una partición dinámica, que puede ser difícil de encontrar con la vista ALL_TAB_SUBPARTITIONS porque el HIGH_VALUE la columna puede no ser simple de consultar. En ese caso se podría utilizar DBMS_ROWID para encontrar la subpartición object_id de una fila dada:

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

Gracias por la publicación, fue muy útil para mí.

Una observación de que en el guión anterior para identificar la partición y eliminarlo:

El object_id devuelto por dbms_rowid.rowid_info no es el object_id de la mesa all_objects. En realidad es el data_object_id. Se observa que generalmente estos identificadores coinciden. Sin embargo, después de truncar la tabla particionada varias veces, estos identificadores divergieron en mi base de datos. Por lo tanto, podría ser razonable usar en su lugar la data_object_id para averiguar el nombre de la partición:

número de objetos
select object_name, subobject_name, object_type 
from all_objects where data_object_id = '15838049'; 

From the table description of ALL_OBJECTS: 

OBJECT_ID del objeto número de objetos DATA_OBJECT_ID del segmento que contiene el objeto

http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_rowid.htm

En el código de ejemplo proporcionado en el enlace anterior, DBMS_ROWID.ROWID_OBJECT(row_id) se usa en su lugar para derivar la misma información que se da por dbms_rowid.rowid_info. Sin embargo, la documentación en torno a esta muestra menciona que es un número de objeto de datos de ROWID.

Ejemplos

Este ejemplo devuelve el ROWID para una fila en la tabla EMP, extractos el número del objeto de datos de la ROWID, usando la función ROWID_OBJECT en el paquete DBMS_ROWID, a continuación, muestra el número de objeto:

DECLARAR object_no INTEGER; row_id ROWID; ...COMIENZO
SELECCIONAR ROWID EN row_id FROM emp DÓNDE empno = 7499; object_no: = DBMS_ROWID.ROWID_OBJECT (row_id); DBMS_OUTPUT.PUT_LINE ('El obj. # Es ' || object_no); ...

Cuestiones relacionadas