ronald.vargas.quesada@gmail.com / Blog de Tecnologías Oracle desde 2009, San José, Costa Rica, 23 de Febrero 17 Aniversario -"No vivas para que tu presencia se note, sino para que tu ausencia se sienta" Bob Marley. Peter Drucker "No hay nada más inútil que hacer con gran eficiencia aquello que nunca debió hacerse."
Hace muchos años, cuando aún las redes sociales, no eran un distractor para todo y apenas se ponía de moda el teléfono celular solo para llamadas y algunos cuantos mensajes SMS, tuve uno de los "lapsus mentalis" más costosos.
Estaba en medio de una depuración de un procedimiento y necesitaba cambiar las características de una tabla, cuando en ese momento sonó el teléfono.
Pude haber ignorado la llamada, pero era de mi casa, así que procedí a contestar. En ese momento sucedido, sucedido una cadena de acontencimientos que terminaron con el borrado accidental de la tabla de producción y no de la tabla temporal de pruebas.
Ya lo sabía con anticipación, el cerebro humano de los hombres, no tiene la capacidad de multiprocesamiento en línea, pero aún así, lo intenté y me equivoqué.
"La experiencia es una maestra muy cara, pero los necios no aprenden de otra."
Nunca más cuando debí contestar un teléfono, continuaba con las manos en el teclado, la lección fue muy dura y como decimos por acá, "al mejor mono se le cae el zapote" y a veces algo más.
Es un paquete pequeño, pero contiene más elementos de los que normalmente se utilizan. Su propósito principal es permitir que el código PL/SQL sea compatible entre distintas versiones de Oracle mediante compilación condicional y comprobaciones de versión.
Este paquete expone constantes que permiten identificar la versión mayor, la release y comprobar características específicas de la base de datos.
Una de las razones por las que existe este paquete es permitir escribir código compatible con varias versiones de Oracle.
El paquete principalmente es llamado a través de sus constantes VERSION y RELEASE, no expone procedimientos, funciones ni parámetros, sino únicamente constantes públicas como:
Además de VERSION y RELEASE, el paquete define constantes booleanas que permiten saber si el código se está compilando para una determinada versión.
En la versión de base de datos Oracle AI Database 26ai, podemos observar en el código, como las constantes para las versiones de base de datos 11.1 hacia atrás han sido marcadas como obsoletas.
Las constantes VER_LEx, son especialmente útiles cuando el objetivo es mantener compatibilidad hacia atrás.
LINE TEXT
---------- ------------------------------------------------------------------------------
1 package dbms_db_version is
2 version constant pls_integer :=
3 23; -- RDBMS version number
4 release constant pls_integer := 0; -- RDBMS release number
5
6 /* The following boolean constants follow a naming convention. Each
7 constant gives a name for a boolean expression. For example,
8 ver_le_9_1 represents version <= 9 and release <= 1
9 ver_le_10_2 represents version <= 10 and release <= 2
10 ver_le_10 represents version <= 10
11
12 Code that references these boolean constants (rather than directly
13 referencing version and release) will benefit from fine grain
14 invalidation as the version and release values change.
15
16 A typical usage of these boolean constants is
17
18 $if dbms_db_version.ver_le_10 $then
19 version 10 and ealier code
20 $elsif dbms_db_version.ver_le_11 $then
21 version 11 code
22 $else
23 version 12 and later code
24 $end
25
26 This code structure will protect any reference to the code
27 for version 12. It also prevents the controlling package
28 constant dbms_db_version.ver_le_11 from being referenced
29 when the program is compiled under version 10. A similar
30 observation applies to version 11. This scheme works even
31 though the static constant ver_le_11 is not defined in
32 version 10 database because conditional compilation protects
33 the $elsif from evaluation if the dbms_db_version.ver_le_10 is
34 TRUE.
35 */
36
37 /* Deprecate boolean constants for unsupported releases */
38
39 ver_le_9_1 constant boolean := FALSE;
40 PRAGMA DEPRECATE(ver_le_9_1);
41 ver_le_9_2 constant boolean := FALSE;
42 PRAGMA DEPRECATE(ver_le_9_2);
43 ver_le_9 constant boolean := FALSE;
44 PRAGMA DEPRECATE(ver_le_9);
45 ver_le_10_1 constant boolean := FALSE;
46 PRAGMA DEPRECATE(ver_le_10_1);
47 ver_le_10_2 constant boolean := FALSE;
48 PRAGMA DEPRECATE(ver_le_10_2);
49 ver_le_10 constant boolean := FALSE;
50 PRAGMA DEPRECATE(ver_le_10);
51 ver_le_11_1 constant boolean := FALSE;
52 PRAGMA DEPRECATE(ver_le_11_1);
53 ver_le_11_2 constant boolean := FALSE;
54 ver_le_11 constant boolean := FALSE;
55 ver_le_12_1 constant boolean := FALSE;
56 ver_le_12_2 constant boolean := FALSE;
57 ver_le_12 constant boolean := FALSE;
58 ver_le_18 constant boolean := FALSE;
59 ver_le_19 constant boolean := FALSE;
60 ver_le_20 constant boolean := FALSE;
61 ver_le_21 constant boolean := FALSE;
62 ver_le_23 constant boolean := TRUE;
63
64 end dbms_db_version;
64 rows selected.
SQL>
Esta es una funcionalidad poco conocida pero que tiene más de 20 años de existencia.
[oracle@oracle-server-26ai ~]$ sqlplus /nolog
SQL*Plus: Release 23.26.2.0.0 - Production on Wed Jul 22 00:12:04 2026
Version 23.26.2.0.0
Copyright (c) 1982, 2026, Oracle. All rights reserved.
SQL> connect / as sysdba
Connected.
SQL> show pdbs
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 PDB1 READ WRITE NO
SQL> alter session set container=pdb1;
Session altered.
PL/SQL procedure successfully completed.
El paquete no devuelve la versión completa de la base de datos, sólo la versión base
SQL> set serveroutput on
SQL> begin
dbms_output.put_line(
dbms_db_version.version
);
end;
/
23
PL/SQL procedure successfully completed.
Podemos generar una versión de la consulta ampliada para poder mostrar un poco más de información utilizando la constante RELEASE
SQL> set serveroutput on
declare
begin
dbms_output.put_line('Oracle Version');
dbms_output.put_line('--------------');
dbms_output.put_line( dbms_db_version.version || '.' ||
dbms_db_version.release );
dbms_output.put_line('Compatible: ' ||
dbms_db_version.version || '.' ||
dbms_db_version.release
);
end;
/
Oracle Version
--------------
23.0
Compatible: 23.0
PL/SQL procedure successfully completed.
Compilación condicional Oracle permite usar directivas especiales:
$IF
$THEN
$ELSE
$END
Estas son evaluadas por el compilador.
Por ejemplo:
SQL> DECLARE
x number;
BEGIN
$IF DBMS_DB_VERSION.VERSION >= 23 $THEN
x := 10;
$ELSE
x := 20;
$END
DBMS_OUTPUT.PUT_LINE('Valor de x: '||x);
END;
/
Valor de x: 10
PL/SQL procedure successfully completed.
En este caso el compilador dependiendo la versión en la cuál compiles el programa, así será la generación del código que utilice. por eso en la ejecución del procedimiento en la versión 26.23.2 devuelve el valor 10 Pero si ejecutamos el mismo código en una versión 19c, el resultado será 20.
SQL> select BANNER_FULL from v$version;
BANNER_FULL
--------------------------------------------------------------------------------
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.22.0.0.0
SQL> DECLARE
x number;
BEGIN
$IF DBMS_DB_VERSION.VERSION >= 23 $THEN
x := 10;
$ELSE
x := 20;
$END
DBMS_OUTPUT.PUT_LINE('Valor de x: '||x);
END;
/
Valor de x: 20
PL/SQL procedure successfully completed.
Todo esto esta muy bien, pero el procedimiento va más allá. Podemos utilizar las constantes boleanas, para determinar cuál es la versión de la base de datos de tal forma que basado en el valor obtenido, ejecute la parte del código que corresponda.
Ejecutando en Oracle AI Database 26ai.
SQL> DECLARE
x NUMBER;
BEGIN
IF DBMS_DB_VERSION.VER_LE_19 THEN
x := 10;
ELSIF DBMS_DB_VERSION.VER_LE_23 THEN
x := 13;
ELSE
x := 20;
END IF;
DBMS_OUTPUT.PUT_LINE('Valor de x: ' || x);
END;
/
Valor de x: 13
PL/SQL procedure successfully completed.
Ahora veamos un ejemplo de ejecución sobre una acción real a nivel de la base de datos. Necesitamos crear un procedimiento que sea capaz de borrar una tabla, pero que dependiendo de la versión que sea, utilice el método con el condicionamiento IF EXISTS o simplemente un DROP TABLE, al no existe la validación, como en versiones 19c o previas.
#### Oracle 19c
SQL> create table t1( x number, y char);
Table created.
SQL> desc t1
Name Null? Type
---------------------- -------- ----------
X NUMBER
Y CHAR(1)
Al ejecutar el procedimiento con el IF EXISTS en 19c, provoca que el procedimiento genere un error de ejecución ORA-00933
SQL> set serveroutput on
SQL> DECLARE
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE IF EXISTS t1';
DBMS_OUTPUT.PUT_LINE('Tabla T1 eliminada (si existía).');
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
/
ORA-00933: SQL command not properly ended
PL/SQL procedure successfully completed.
Ahora hagamos el mismo proceso, pero con la sintáxis aceptada en 19c.
SQL> DECLARE
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE t1';
DBMS_OUTPUT.PUT_LINE('Tabla T1 eliminada.');
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -942 THEN
DBMS_OUTPUT.PUT_LINE('La tabla T1 no existe.');
ELSE
RAISE;
END IF;
END;
/
Tabla T1 eliminada.
PL/SQL procedure successfully completed.
SQL> create table t1( x number, y char);
Table created.
Ahora agreguemos la opción de compilación condicional al script, para que no nos genere error en la versión 19c.
DECLARE
BEGIN
$IF DBMS_DB_VERSION.VERSION >= 23 $THEN
EXECUTE IMMEDIATE 'DROP TABLE IF EXISTS t1';
$ELSE
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE t1';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -942 THEN
RAISE;
END IF;
END;
$END
DBMS_OUTPUT.PUT_LINE('Proceso finalizado.');
END;
/
Proceso finalizado.
PL/SQL procedure successfully completed.
SQL> desc t1
ERROR:
ORA-04043: object t1 does not exist
SQL>
En la version de Oracle AI Database 26ai, ambas instrucciones serán ejecutadas sin presentar ningún error, ya que ambas son válidas.
##Oracle 26ai
SQL> create table t1( x number, y char);
Table created.
SQL> DECLARE
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE t1';
DBMS_OUTPUT.PUT_LINE('Tabla T1 eliminada.');
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -942 THEN
DBMS_OUTPUT.PUT_LINE('La tabla T1 no existe.');
ELSE
RAISE;
END IF;
END;
/
Tabla T1 eliminada.
PL/SQL procedure successfully completed.
¿Por qué Oracle diseñó este mecanismo?
Esto lo hizo pensado principalmente para fabricantes de software (ISVs) y equipos que mantienen una misma base de código para múltiples versiones de Oracle. Por ejemplo, un producto que debe soportar Oracle 19c, 21c y 23ai puede distribuir el mismo código fuente y dejar que cada base de datos compile automáticamente la variante adecuada.
El dato histórico interesante:
Aunque el paquete existe desde 9.2, su verdadero protagonismo llegó con PL/SQL Conditional Compilation, introducida en Oracle Database 10g Release 2 (10.2). Fue entonces cuando Oracle empezó a recomendar expresiones como:
$IF DBMS_DB_VERSION.VER_LE_10 $THEN
-- Código para Oracle 10g o anterior
$ELSIF DBMS_DB_VERSION.VER_LE_11 $THEN
-- Código para Oracle 11g
$ELSE
-- Código para versiones posteriores
$END
Antes de 10.2 el paquete ya existía, pero no podía aprovecharse con este mecanismo de compilación condicional, que es precisamente el uso para el que fue diseñado
Esta característica recién ha cumplido 24 años de existencia. La conocías.?
Hace unos días empecé a ver Ted Lasso. Curiosamente, después de una copa de vino, la serie me llevó a pensar en algo que he visto repetirse durante más de treinta años trabajando en tecnología.
No hablo de servidores, bases de datos o proyectos.
Hablo de personas.
Con el tiempo uno descubre que no todas las contrataciones persiguen el mismo objetivo.
Hay empresas que contratan para construir.
Otras contratan para transformar.
Pero también existen aquellas que contratan para encontrar a quién cargarle el peso de un fracaso que comenzó mucho antes de que esa persona llegara.
Es una realidad incómoda.
Muchas veces creemos que nos buscan porque somos la mejor opción para resolver un problema complejo. Nos ilusiona pensar que podremos aportar nuestra experiencia, ordenar el caos y dejar una organización mejor de como la encontramos.
Sin embargo, en algunas ocasiones el desenlace ya estaba decidido.
El presupuesto ya estaba agotado.
La confianza ya estaba rota.
La dirección ya había perdido el rumbo.
Las decisiones importantes ya habían sido tomadas.
Y la contratación no era el comienzo de un rescate, sino el último acto antes del cierre del telón.
No eres el capitán del barco.
Eres el nombre que aparecerá en el informe final.
Durante mi carrera he visto excelentes profesionales fracasar en lugares donde, simplemente, nadie podía tener éxito.
Personas inteligentes, responsables y comprometidas que terminaron cuestionando su capacidad, cuando en realidad habían sido colocadas en un escenario donde el resultado estaba condicionado desde el primer día.
En informática esto ocurre con frecuencia.
Llega un nuevo gerente de TI cuando la empresa lleva años sin invertir.
Contratan un DBA cuando las políticas de respaldo nunca existieron.
Incorporan un arquitecto cuando el sistema acumula veinte años de deuda técnica.
Nombran un líder cuando el equipo perdió la confianza hace mucho tiempo.
Después, cuando nada cambia en unos cuantos meses, la conclusión parece sencilla:
"El nuevo tampoco funcionó."
Pero la pregunta correcta casi nunca es esa.
La pregunta debería ser:
¿Realmente alguien quería que funcionara?
Con los años también entendí que este fenómeno no pertenece únicamente al mundo laboral. Sucede en las relaciones personales.
Hay personas que llegan intentando reconstruir vínculos que llevan años deteriorándose. Intentan comunicarse. Intentan comprender. Intentan cambiar.
Mientras la otra parte ya tomó la decisión de irse hace mucho tiempo.
No buscan reconstruir. Buscan confirmar que ya no había nada por hacer.
Y entonces aparece alguien dispuesto a luchar una batalla que ya había terminado antes de comenzar.
La experiencia, sin embargo, también enseña algo esperanzador.
No todos los desafíos imposibles son una trampa. Algunas de las mejores historias profesionales nacen precisamente de proyectos que parecían condenados. La diferencia suele estar en algo que pocas veces aparece en una descripción de puesto.
La voluntad real de cambiar. Cuando existe esa voluntad, incluso con pocos recursos, los equipos encuentran caminos.
Cuando no existe, ni el mejor profesional del mundo puede fabricar compromiso donde nadie quiere asumirlo.
Si pudiera dar un consejo a quienes apenas comienzan su carrera, no sería "acepten todos los retos".
Sería algo distinto. Aprendan primero a identificar la naturaleza del desafío. Antes de aceptar un puesto, hagan preguntas difíciles:
¿Por qué se fue la persona anterior?
¿Cuántas personas han ocupado ese cargo en los últimos años?
¿Qué decisiones puede tomar realmente quien ocupe el puesto?
¿Existe presupuesto para cambiar las cosas?
¿La dirección está dispuesta a modificar aquello que provocó el problema?
Las respuestas a esas preguntas suelen revelar mucho más que una entrevista de una hora.
El talento es importante.
Pero también lo es elegir las batallas correctas.
Y para quienes ya acumulamos algunas décadas de experiencia, el aprendizaje quizá sea diferente.
No debemos confundir resiliencia con sacrificio infinito.
No tenemos que demostrar constantemente que podemos salvar cualquier proyecto.
Hay momentos en que la mayor muestra de madurez profesional consiste en reconocer que una organización no busca soluciones.
Busca un responsable.
Y son dos cosas completamente distintas.
Decir "no" también forma parte de la experiencia.
Renunciar antes de convertirnos en el chivo expiatorio de decisiones ajenas también es una forma de proteger nuestra integridad profesional.
No porque tengamos miedo de fracasar.
Sino porque entendimos que no todo fracaso nos pertenece.
Después de tantos años sigo creyendo que las personas pueden cambiar organizaciones.
He visto equipos extraordinarios lograr cosas que parecían imposibles.
Pero también aprendí que ninguna persona, por brillante que sea, puede reemplazar la voluntad colectiva de hacer que las cosas no funcionen.
Hay barcos que todavía pueden repararse. Y hay barcos que solo buscan un nuevo capitán para explicar por qué terminaron hundiéndose.
La experiencia consiste, precisamente, en aprender a distinguir unos de otros.
Porque, al final, el verdadero éxito profesional no siempre consiste en salvar todos los barcos.
A veces consiste en reconocer cuáles todavía quieren navegar.
No me hagan mucho caso, yo ya estoy un poco viejo y creo que la entrada en años me empieza a pasar factura.
Solo tengan presente una cosa, la vida es corta, mucho más de lo que crees cuando tienes 20, 30 o 40 años. Despues de los 50's, sólo piensas en una cosa: Como tener paz y como vivir bien.
Algunos dirán que con 58 años, aún me queda mucho por hacer. Y si, tienen mucha razón, pero mis prioridades actuales, son muy distintas a las de hace 20 años atrás.
En ocasiones, desearía correr detrás de un balón, saltar y golpearlo como lo hacía cuando tenía 20. Pero la realidad es otra. Mi cuerpo me lo recuerda cada mañana al levantarme y cada día al final. Ya no soy lo mismo y nunca más lo volveré a hacer. Esa es la realidad.
Lo único que nunca deberíamos permitirnos es cargar con la culpa de un fracaso cuya causa nunca estuvo en nuestras manos.
El Independent Automaton de Fleet Patching and Provisioning, también descrito por Oracle internamente en el contexto de FPP Local Mode, es una herramienta diseñada para realizar out-of-place patching entre dos ORACLE_HOME instalados en el mismo servidor, incluso cuando:
no existe Oracle Grid Infrastructure;
no existe Oracle Restart;
no existe un servidor FPP central;
los Oracle Homes no son working copies;
los Homes fueron instalados mediante runInstaller u otro método convencional.
Oracle permite a través de esta opción que 2 ORACLE_HOME instalados y no administrados por un servidor FPP, pueden ser migrados o actualizados.
La versión disponible del FPP en modo local solo dispone de un comando:
commands: move
objects: database
No contiene las funciones completas de un servidor o cliente FPP, como:
rhpctl add image
rhpctl add workingcopy
rhpctl query job
rhpctl deploy home
rhpctl move gihome
rhpctl upgrade database
rhpctl -version
y esto no esta mal, ya que es el comportamiento esperado en la versión autónoma.
La herramienta identifica las bases asociadas al Home origen y las cambia al Home destino.
Mi escenario para este laboratorio es el siguiente:
FPP integra la ejecución de datapatch como parte del movimiento, salvo que se le indique explícitamente no hacerlo.
Un punto importante mientras no se elimine ni modifique el Home de origen, puede realizarse el movimiento inverso.
No obstante, debe distinguir entre:
retornar los binarios al Home anterior;
revertir los cambios SQL aplicados por datapatch.
Después de que el RU nuevo haya modificado el diccionario, el retorno no debe tratarse simplemente como un cambio de variables. El procedimiento debe considerar el rollback SQL del RU, la compatibilidad y las opciones que soporte rhpctl. Por ello, el Home anterior debe conservarse hasta completar todas las validaciones funcionales.
A continuación podrás ver el procedimiento completo para realizar el cambio o actualización que describí previamente.
[oracle@oracle-server-26ai bin]$ ./rhpctl move database -h
Moves a database from source Oracle home to the patched Oracle home.
Usage: rhpctl move database -sid -sourcehome
-desthome
[-eval]
[-ignorewcpatches]
[-stopoption ]
[-drain_timeout
En mis charlas sobre "Ethical Hacking", me encanta hablar sobre “Neutralidad en Seguridad”. Me gusta ampliar el principio clásico de mínimo privilegio desde una perspectiva puramente técnica, hacia una dimensión de gobernanza, responsabilidad y protección del propio usuario.
El principio tradicional de mínimo privilegio (Principle of Least Privilege, PoLP) establece:
Una identidad (usuario, aplicación, proceso o servicio) debe recibir únicamente los privilegios estrictamente necesarios para ejecutar sus funciones autorizadas, durante el tiempo necesario y bajo las condiciones necesarias.
Sin embargo mi concepto agrega una capa adicional: un exceso de privilegios no solo incrementa el riesgo para la organización, sino que rompe la neutralidad del usuario frente a un incidente.
Para mi: Neutralidad en seguridad: es el principio mediante el cual los privilegios asignados a una identidad digital deben mantenerse alineados estrictamente con sus responsabilidades reales, evitando que permisos innecesarios conviertan a dicha identidad en un punto injustificado de exposición, sospecha o atribución dentro de un incidente de seguridad.
El punto central desde mi perspectiva, es que la neutralidad ocurre cuando, los Permisos concedidos = Responsabilidad funcional. Ni menos, ni más.
Desde el punto de vista de seguridad, un exceso de privilegios genera varios problemas:
1. Incrementa la superficie de ataque
Ejemplo en base de datos:
Un analista requiere:
SELECT sobre tablas de reportes,
pero recibe: SELECT ANY TABLE o peor aún "DBA".
El atacante hereda todo lo que la cuenta puede hacer, no solamente lo que el usuario normalmente hace.
2. Rompe la presunción operacional de inocencia.
Supongamos:
Usuario A: necesita consultar clientes, tiene acceso solo lectura
Usuario B: necesita consultar clientes, pero además tiene: borrar registros, exportar información, crear usuarios, modificar privilegios.
Si ocurre una fuga, desde un análisis forense el Usuario A:
¿Tenía capacidad técnica?
Respuesta: NO, menor probabilidad como origen.
En el caso del Usuario B:
¿Tenía capacidad técnica?
Respuesta: SÍ, debe investigarse. Aunque Usuario B sea inocente, los privilegios excesivos lo colocaron dentro del perímetro de sospecha.
3. La asignación excesiva de permisos crea responsabilidad compartida
Una frase que resume bien el concepto:
"Todo privilegio innecesario es una responsabilidad innecesaria transferida al usuario."
Dar privilegios no es solamente dar capacidad, también es asignar:
Tenemos un script para validar el crecimiento de objetos dentro de la base de datos en los últimos 6 días y cuando ejecutamos la consulta nos devuelve la siguiente salida.
El script en cuestión es el siguiente, asociado a una vista para poderlo ejecutar más fácil:
create view v_tablas_mas_crecimiento as
WITH snaps AS (
SELECT
MIN(snap_id) AS begin_snap,
MAX(snap_id) AS end_snap
FROM dba_hist_snapshot
WHERE begin_interval_time >= SYSDATE - 6
),
seg_begin AS (
SELECT
obj.owner,
obj.object_name AS segment_name,
obj.object_type AS segment_type,
ss.space_used_delta
FROM dba_hist_seg_stat ss
JOIN dba_hist_seg_stat_obj obj
ON obj.dbid = ss.dbid
AND obj.obj# = ss.obj#
AND obj.dataobj# = ss.dataobj#
JOIN snaps sn
ON ss.snap_id = sn.begin_snap
),
seg_growth AS (
SELECT
obj.owner,
obj.object_name AS segment_name,
obj.object_type AS segment_type,
SUM(ss.space_used_delta) AS growth_bytes
FROM dba_hist_seg_stat ss
JOIN dba_hist_seg_stat_obj obj
ON obj.dbid = ss.dbid
AND obj.obj# = ss.obj#
AND obj.dataobj# = ss.dataobj#
WHERE ss.snap_id BETWEEN (SELECT begin_snap FROM snaps)
AND (SELECT end_snap FROM snaps)
GROUP BY obj.owner, obj.object_name, obj.object_type
)
SELECT *
FROM (
SELECT
owner,
segment_name,
segment_type,
ROUND(growth_bytes/1024/1024,2) AS growth_mb
FROM seg_growth
WHERE growth_bytes > 0
ORDER BY growth_bytes DESC
)
WHERE ROWNUM <= 20;
select * from "V_TABLAS_MAS_CRECIMIENTO";
Qué son estos datos en el nombre del objeto ** MISSING: 6591054/6591054 ?
Vamos a explicarlo.
En Oracle, cuando estás consultando crecimiento histórico (normalmente desde AWR usando DBA_HIST_SEG_STAT y DBA_HIST_SEG_STAT_OBJ) y en lugar del nombre del objeto aparece algo como:
** MISSING: 6624752/6624752
significa que AWR tiene estadísticas históricas de un segmento, pero ya no puede resolver el objeto asociado en el diccionario histórico de objetos.