lunes, 5 de julio de 2010

Como habilitar la opción de DEBUG en el TOAD?

Pasos

El usuario necesita tener el privilegio 'DEBUG CONNECT SESSION'. Si el mismo no fue granteado, el icono de debugger estará deshabilitado en el editor de pl/sql.


Solución

1. Grant debug any procedure to user_name;
2. Grant debug connect session to user_name;

Si es necesario tambien ejecutar:

1. GRANT EXECUTE ON DBMS_DEBUG to public;
2. Si, DBMS_DEBUG no esta creado, ejecutar el archivo $ORACLE_HOME\rdbms\admin\prvtpb.plb con el usuario SYS.

jueves, 17 de junio de 2010

Configurar Toad y sqlplus, usando Oracle Instant Client


Instant Client Package – Basic
Instant Client Package - SQL*Plus

Paso 2. Creamos cuatro carpetas como se muestra debajo.

C:\oracle
C:\oracle\bin
C:\racle\network
C:\oracle\network\admin
Paso 3. Descomprimimos los binarios dentro de c:\oracle\bin y nos aseguramos que exita el archivo oci.dll y sqlplus.exe.
Luego dentro de la carpeta admin alojamos los archivos tnsnames.ora y sqlnet.ora

tnsnames.ora


ALIAS_XE =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = x.x.x.x)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = XE)
)

sqlnet.ora

SQLNET.AUTHENTICATION_SERVICES = (NTS)

Paso 4. Creamos las siguientes variables de sistema. Vamos a mi pc > propiedades > configuración avanzada del sistema > Variables de entorno


Y agregamos:

ORACLE_HOME = C:\oracle
ORACLE_HOME_NAME = C:\oracle
SQL_PATH = C:\oracle
TNS_ADMIN = C:\oracle\network\admin
LD_LIBRARY_PATH = C:\oracle\bin
PATH= C:\oracle\bin;

Paso 5. Probamos hacer la conexión con el Toad y el sqlplus.

jueves, 5 de noviembre de 2009

Como particionar una tabla en linea?

Supongamos que tenemos una tabla, esta puede estar o no particionada y la idea en este caso puntual es volver a particionarla por mes con creación de particiones en forma automática. Para esta tarea vamos a utilizar el pakage DBMS_REDEFINITION.

paso 1.

El primer paso es chequear si la tabla se puede redefinir online, si la salida del script mostrado debajo no da ningún error, entonces podemos hacer uso del packages DBMS_REDEFINITION.

DECLARE
ndummy NUMBER;
begin
DBMS_REDEFINITION.CAN_REDEF_TABLE('SCHEMA','TABLA_ORIGINAL');
EXCEPTION
WHEN OTHERS THENRAISE;
end;
/

Paso 2.

Creamos la tabla temporal con la nueva estructura, en mi caso sólo la particioné por otro campó y ademas lo hice por mes utilizando la clausula "INTERVAL( NUMTOYMINTERVAL(1,'MONTH'))" provista en 11g la cual hace que las partiones se creen en forma automática.

NOTA:
- Para no generar archive's cambiar a modo NOLOGGING tanto la definición de la tabla como el clob.
- Crear las particiones necesarias para alojar la tabla completa.
- Hay que asegurarnos de tener espacio en el tablespace, mínimo el tamaño de la tabla original y un poco más.
- Debe tener la misma PK que la Original.
- En este punto no se debe crear ningún indice ni constraint ni trigger que no sea la PK.
- La tabla debe ser creada con los cambios deseados. - La tabla temporal debe ser creada con esos cambios.

--prompt creo la tabla temporal

CREATE TABLE SCHEMA.DOCUMENTOS_TEMP
(
IDNS_DOCUMENTO NUMBER NOT NULL,
SD_ANIO NUMBER(4) NOT NULL,
SD_ADUANA VARCHAR2(3 CHAR) NOT NULL,
SD_DOCUMENTOTIPO VARCHAR2(4 CHAR) NOT NULL,
SD_DOCUMENTONRO VARCHAR2(6 CHAR) NOT NULL,
SD_LETRA VARCHAR2(1 CHAR) NOT NULL,
SG_DOCUMENTO BLOB NOT NULL,
SD_CAJA VARCHAR2(6 CHAR) NOT NULL,
NS_DESPACHANTE NUMBER NOT NULL,
SD_CUITDESPACHANTE VARCHAR2(11 CHAR) NOT NULL,
SD_DESPACHANTE VARCHAR2(100 CHAR) NOT NULL,
NS_IMPORTADOREXPORTADOR NUMBER NOT NULL,
SD_CUITIMPORTADOREXPORTADOR VARCHAR2(11 CHAR) NOT NULL,
SD_IMPORTADOREXPORTADOR VARCHAR2(100 CHAR) NOT NULL,
H_ALTA DATE DEFAULT SYSDATE NOT NULL,
NC_PAGINAS NUMBER(4) NOT NULL,
NC_PAGINASLOTE NUMBER(4),
NC_BYTESPDF NUMBER,
H_UPD DATE
)
TABLESPACE DATA_CLOB
NOLOGGING
PARTITION BY RANGE (H_ALTA)
INTERVAL( NUMTOYMINTERVAL(1,'MONTH'))
(
PARTITION VALUES LESS THAN (TO_DATE(' 2009-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN'))
NOLOGGING
NOCOMPRESS
TABLESPACE DATA_CLOB
LOB (SG_DOCUMENTO) STORE AS
( TABLESPACE DATA_CLOB
ENABLE STORAGE IN ROW
CHUNK 8192
RETENTION
NOCACHE
NOLOGGING
),
PARTITION VALUES LESS THAN (TO_DATE(' 2009-10-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN'))
NOLOGGING
NOCOMPRESS
TABLESPACE DATA_CLOB
LOB (SG_DOCUMENTO) STORE AS
( TABLESPACE DATA_CLOB
ENABLE STORAGE IN ROW
CHUNK 8192
RETENTION
NOCACHE
NOLOGGING
),
PARTITION VALUES LESS THAN (TO_DATE(' 2009-11-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN'))
NOLOGGING
NOCOMPRESS
TABLESPACE DATA_CLOB
LOB (SG_DOCUMENTO) STORE AS
( TABLESPACE DATA_CLOB
ENABLE STORAGE IN ROW
CHUNK 8192
RETENTION
NOCACHE
NOLOGGING
),
PARTITION VALUES LESS THAN (TO_DATE(' 2009-12-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN'))
NOLOGGING
NOCOMPRESS
TABLESPACE DATA_CLOB
LOB (SG_DOCUMENTO) STORE AS
( TABLESPACE DATA_CLOB
ENABLE STORAGE IN ROW
CHUNK 8192
RETENTION
NOCACHE
NOLOGGING
)
)
NOCOMPRESS
NOCACHE
NOPARALLEL
MONITORING;


Paso3.

Asociamos la tabla temporal con la tabla a redefinir.

prompt Iniciar el proceso de redefinición
BEGIN
DBMS_REDEFINITION.START_REDEF_TABLE ('SCHEMA','DOCUMENTOS','DOCUMENTOS_TEMP',
'IDNS_DOCUMENTO IDNS_DOCUMENTO,
SD_ANIO SD_ANIO,
SD_ADUANA SD_ADUANA,
SD_DOCUMENTOTIPO SD_DOCUMENTOTIPO,
SD_DOCUMENTONRO SD_DOCUMENTONRO,
SD_LETRA SD_LETRA, SG_DOCUMENTO
SG_DOCUMENTO, SD_CAJA SD_CAJA,
NS_DESPACHANTE NS_DESPACHANTE,
SD_CUITDESPACHANTE SD_CUITDESPACHANTE,
SD_DESPACHANTE SD_DESPACHANTE,
NS_IMPORTADOREXPORTADOR NS_IMPORTADOREXPORTADOR, SD_CUITIMPORTADOREXPORTADOR SD_CUITIMPORTADOREXPORTADOR, SD_IMPORTADOREXPORTADOR SD_IMPORTADOREXPORTADOR,
H_ALTA H_ALTA,
NC_PAGINAS NC_PAGINAS,
NC_PAGINASLOTE NC_PAGINASLOTE,
NC_BYTESPDF NC_BYTESPDF,
H_UPD H_UPD',
dbms_redefinition.cons_use_pk);
END;
/

Paso4.

Copia las dependencias de la tabla original a la tabla temporal.

prompt Copiar el objeto dependiente

DECLARE
num_errors PLS_INTEGER;
BEGIN
DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS('SCHEMA', 'DOCUMENTOS','DOCUMENTOS_TEMP', DBMS_REDEFINITION.CONS_ORIG_PARAMS, TRUE, TRUE, TRUE, TRUE, num_errors);
END;
/


Paso5.

Hacemos un chequeo de errores.
prompt Consultar la vista DBA_REDEFINITION_ERRORS para saber si hubo algún error.

select object_name, base_table_name, ddl_txt from DBA_REDEFINITION_ERRORS;
Paso6.
Mantenemos sincronizada la tabla temporal con los datos de la tabla original.

prompt Sincronizar la tabla temporal o intermedia

BEGIN
DBMS_REDEFINITION.SYNC_INTERIM_TABLE('SRD', 'DOCUMENTOS','DOCUMENTOS_TEMP');
END;
/


Paso7.

Registra la dependendia de objetos ( indices, trigger o constraint ) y finaliza la redefinición.

prompt Completar la redefinicion

BEGIN
DBMS_REDEFINITION.FINISH_REDEF_TABLE('SRD', 'DOCUMENTOS','DOCUMENTOS_TEMP');
END;
/

Paso8.

Volver a poner en modo LOGGING a la tabla.

alter table SCHEMA.DOCUMENTOS LOGGING ;
alter table SCHEMA.DOCUMENTOS MODIFY LOB (SG_DOCUMENTO) (CACHE LOGGING);

NOTA:

En caso de dar error y querer realizar rollback de la operacion se puede ejecutar lo siguente

BEGIN dbms_redefinition.abort_redef_table('SRD', 'DOCUMENTOS','DOCUMENTOS_TEMP');
END;
/

martes, 19 de mayo de 2009

Como mover datos de la partición default a una nueva?

Cuando tenemos una tabla particionada, en este caso por un rango de fechas y nos damos cuenta que los registros se están creando en la partición default, la solución es crear una nueva particion con el rango adecuado. Para este caso se puede usar la opción SPLIT la cual crea una nueva partición, en mi caso es la partición DCT_DOC2009.

ALTER TABLE dct_documentos
SPLIT PARTITION DCT_DOCMAX at (TO_DATE(' 2010-01-02 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN'))
INTO (PARTITION DCT_DOC2009,
PARTITION DCT_DOCMAX)
UPDATE GLOBAL INDEXES;

Podemos usar la opción UPDATE GLOBAL INDEXES la cual recrea los indices globales de la tabla en cuestión o podriamos eliminar la opción de la claúsula y en un segundo paso recrear los indices con estado UNSUABLE.

Para hacer el reubuild de los indices usamos la siguiente query:

SELECT 'alter index 'owner'.'index_name ' REBUILD;'
FROM dba_indexes
WHERE status='UNUSABLE' ;

Para ver como quedaron las particiones se puede usar el siguiente query:

SELECT partition_name, high_value
FROM user_tab_partitions
WHERE table_name = 'DCT_DOCUMENTOS'
ORDER BY partition_name;

Para confirmar que ahora la partición tiene datos usamos:

SELECT * FROM dct_documentos PARTITION(DCT_DOC2009);

Par confirmar que la particion default en mi caso se llama DCT_DOCMAX, esta query debería no retornar filas.

SELECT * FROM dct_documentos PARTITION(DCT_DOCMAX);

Como calcular el tamaño realmente usado de un segmento

Con este script se puede calcular el tamaño realmente usado por un segmento.


PROMPT
PROMPT SEGMENT SPACE ALLOCATION
PROMPT

ACCEPT own PROMPT "Segment owner: "
ACCEPT obj PROMPT "Segment name: "
ACCEPT typ PROMPT "Segment type ((T)able, (I)ndex or (C)luster) or (L)ob: "

SET HEADING OFF
SELECT ' ' FROM sys.dual;

SET SERVEROUTPUT ON

DECLARE
op1 NUMBER;
op2 NUMBER;
op3 NUMBER;
op4 NUMBER;
op5 NUMBER;
op6 NUMBER;
op7 NUMBER;
obj_type VARCHAR2(10);
file_name VARCHAR2(255);
ts_name VARCHAR2(30);

BEGIN

IF UPPER('&typ') = 'T' THEN
obj_type := 'TABLE';
ELSIF UPPER('&typ') = 'I' THEN
obj_type := 'INDEX';
ELSIF UPPER('&typ') = 'C' THEN
obj_type := 'CLUSTER';
ELSIF UPPER('&typ') = 'L' THEN
obj_type := 'LOB';

ELSE
dbms_output.put_line('Invalid object type');
RETURN;
END IF;

dbms_space.unused_space(
UPPER('&own'),
UPPER('&obj'),
obj_type,
op1, op2, op3, op4, op5, op6, op7
);

dbms_output.put_line('Total Blocks = ' || op1);
dbms_output.put_line('Total Bytes = ' || op2);
dbms_output.put_line('Unused Blocks = ' || op3);
dbms_output.put_line('Unused Bytes = ' || op4);

SELECT file_name, tablespace_name
INTO file_name, ts_name
FROM dba_data_files
WHERE file_id = op5;

dbms_output.put_line('Segment Tablespace = ' || ts_name);
dbms_output.put_line('Last Used Extent File ID = ' || op5);
dbms_output.put_line('Last Used Extent File = ' || file_name);
dbms_output.put_line('Last Used Extent Block ID = ' || op6);
dbms_output.put_line('Last Used Block = ' || op7);

END;
/

UNDEFINE obj
UNDEFINE own
UNDEFINE typ