miércoles, 30 de noviembre de 2016

La Lotería en PL/SQL

Objetivo:
• Presentar un ejemplo práctico en el cual es oportuno utilizar el paquete DBMS_RANDOM.

Nota: Esta publicación no tiene el mínimo interés de fomentar y/o promover los juegos de azar de ningún tipo, quien escribe decidió utilizar el ejemplo de lotería debido a que entendimos que el mismo se presta para dar un idea mas clara de lo util que resulta el paquete DBMS_RANDOM de Oracle.
____________________________________________________________________________________
SET SERVEROUTPUT ON
DECLARE
    TYPE typ_rec_lottery IS RECORD
    (
        number_one      NUMBER,
        number_two      NUMBER,
        number_three    NUMBER
    );

    TYPE typ_tab_lottery IS
        TABLE OF    typ_rec_lottery
            INDEX BY BINARY_INTEGER;

    v_lottery_list      typ_tab_lottery;
    v_lottery_name      VARCHAR2(10);
    v_lottery_time      VARCHAR2(25);

BEGIN
    FOR i IN 1..3 LOOP
        v_lottery_list(i).number_one   :=  TRUNC(DBMS_RANDOM.value(0, 99));
        v_lottery_list(i).number_two   :=  TRUNC(DBMS_RANDOM.value(099));
        v_lottery_list(i).number_three   :=  TRUNC(DBMS_RANDOM.value(099));
    END LOOP;

    FOR i IN 1..v_lottery_list.COUNT LOOP
        CASE
           WHEN i < 2 THEN
                v_lottery_name  :=  'Matutina';
                v_lottery_time  :=  '10:30:00 AM';
           WHEN i > THEN
                v_lottery_name  :=  'Nocturna';
                v_lottery_time  :=  '9:30:00 PM';
           ELSE
                v_lottery_name  :=  'Vespertina';
                v_lottery_time  :=  '3:30:00 PM';
        END CASE;

        DBMS_OUTPUT.PUT_LINE
                           (
                                '<<Lotería  '||v_lottery_name||'>>'||CHR(9)||'Hora: '||v_lottery_time||CHR(10)||
                                'Primer Número: '||v_lottery_list(i).number_one||CHR(10)||
                                'Segundo Número: '||v_lottery_list(i).number_two||CHR(10)||
                                'Tercer Número: '||v_lottery_list(i).number_three||CHR(10)||
                                RPAD('-',40,'-')
                           );
    END LOOP;
END;
/**/
---OUTPUT:

martes, 29 de noviembre de 2016

Generando Valores Aleatorios con DBMS_RANDOM

Objetivos:
• Conocer el paquete DBMS_RANDOM.
• Describir sus Funciones y Procedimientos.
• Presentar ejemplos prácticos y funcionales.

NOTA: Usamos como ejemplo la Base de Datos: ORCL, la cual viene por defecto en cualquier versión de ORACLE.
____________________________________________________________________________________
Paquete DBMS_RANDOM
Dependiendo del requerimiento se pueden presentar escenarios en los cuales sea necesario generar valores aleatorios, ya sea para crear una gran cantidad de datos para propósitos de prueba de desempeño, o cuando simplemente necesitamos asignar un número X a un proceso.

Cualquiera que sea la necesidad, Oracle provee el Paquete DBMS_RANDOM que permite generar valores  numéricos, tipo carácter y cadenas alfanuméricas de forma aleatoria. Tenga presente que es posible especificar el tamaño y el rango a ser usado en la generación de los valores aleatorios.

Nota: En este paquete podemos ver como la sobrecarga de procedimientos y funciones es posible dentro de Bloques de PL/SQL tales como: Bloques anónimos, Subprogramas y Paquetes. Es decir, puede utilizar el mismo nombre para varios subprogramas diferentes, siempre y cuando sus parámetros difieran en número, orden o tipos de dato.

Lista de Procedimientos/Funciones Disponibles:
Subprogram
Description
Procedimiento INITIALIZE
Inicializa el paquete con un valor de semilla (SEED value).
Función NORMAL
Retorna números aleatorios en una distribución normal.
Procedimiento RANDOM
Genera números aleatorios.
Procedimientos SEED
Restablece la semilla. Dicho procedimiento contiene una versión que recibe un parámetro BINARY_INTEGER(numérico) y una sobrecarga que recibe un tipo VARCHAR2(carácter).
Función STRING
Genera una cadena aleatoria.
Procedimiento TERMINATE
Finaliza el paquete.
Funciones VALUE
Esta función(sin parámetros) genera una numero aleatorio mayor o igual a 0 pero menor que 1. Su sobrecarga(con dos parámetros) genera un número aleatorio mayor o igual que el limite inferior(parámetro low) y menor que el limite superior(parámetro high). Ambas versiones tienen una precisión de 38 dígitos a la derecha del decimal.
Procedimiento INITIALIZE
Este procedimiento inicializa el generador. En síntesis este procedimiento es obsoleto ya que su función es simplemente llamar a los Procedimientos de SEED.
---
Función NORMAL
Esta función retorna números aleatorios en una distribución normal estándar.
---
Procedimiento RANDOM
Este procedimiento genera números aleatorios. Al igual que INITIALIZE, es considerado obsoleto y, aunque viene incluido en el paquete, no se recomienda su uso.
---
Procedimientos SEED
Estos procedimientos restablecen la semilla usada para generar números/cadenas aleatorias.
---
Función STRING
Esta función genera una cadena aleatoria. La misma recibe dos parámetros descritos a continuación:
Parámetro
Descripción
opt
Es usado para especificar el aspecto de la cadena de retorno:
  •  'u', 'U' – Retorna una cadena de caracteres alfabéticos en mayúsculas.
  •  'l', 'L' - Retorna una cadena de caracteres alfabéticos en minúsculas.
  •  'a', 'A' - Retorna una cadena de caracteres alfabéticos mixta (mayúsculas y minúsculas).
  •  'x', 'X' - Retorna una cadena de caracteres alfanuméricos en mayúsculas.
  •  'p', 'P' - Retorna una cadena de cualquier carácter imprimible.
Si no se especifica uno de los valores anteriores, se retorna una cadena de caracteres alfabéticos en mayúsculas.
len
Longitud de la cadena retornada.
Procedimiento TERMINATE
Se supone que una vez se haya terminado con el paquete, se debería llamar al procedimiento TERMINATE, pero realmente este no realiza función alguna y, aunque viene incluido en el paquete, es obsoleto y no debe utilizarse.
---
Funciones VALUE
Como ya especificamos, la función básica(sin parámetros) genera un número aleatorio, mayor o igual a 0 y menor que 1. La sobrecarga recibe dos parámetros (low y high) y retorna un numero mayor o igual que el primero (low) y menor que el segundo (high).
____________________________________________________________________________________
Ejemplos:
SELECT
        DBMS_RANDOM.NORMAL,
        DBMS_RANDOM.RANDOM,
        DBMS_RANDOM.string('U', 8),
        DBMS_RANDOM.string('L'8),
        DBMS_RANDOM.string('K'8),
        DBMS_RANDOM.VALUE,
        DBMS_RANDOM.VALUE(20,60)
FROM dual;
/*En este ejemplo invocamos las funciones */
---OUTPUT:
CREATE TABLE hr.calificaciones
(
    cod_estudiante      NUMBER(6),          --Código Estudiante
    cod_semestre        NUMBER(1)           --Código Semestre
                            CONSTRAINT ck_sem CHECK(cod_semestre IN (1,2)),
    espanol             NUMBER(3),      --no es recomendable usar la ñ para nombre de objectos de Base de Datos
    matematicas         NUMBER(3),
    sociales            NUMBER(3),
    naturales           NUMBER(3),

    CONSTRAINT pk_calif PRIMARY KEY (cod_estudiante, cod_semestre),
    CONSTRAINT ck_calif CHECK  --Constraint para limitar el rango de las calificaciones.
                           (
                                (espanol BETWEEN 1 AND 100)
                                AND
                                (matematicas BETWEEN 1 AND 100)
                                AND
                                (sociales BETWEEN 1 AND 100)
                                AND
                                (naturales BETWEEN 1 AND 100)
                           )
);
/*Creamos la tabla calificaciones para mostrar un ejemplo mas práctico del paquete DBMS_RANDOM.*/
---
DECLARE
    v_rec_calif     hr.calificaciones%ROWTYPE;
BEGIN
    FOR i IN 1..10 LOOP    --LOOP para los estudiantes...
        FOR j IN 1..LOOP   --LOOP para los semestres...
            v_rec_calif.cod_estudiante := i;
            v_rec_calif.cod_semestre := j;
            v_rec_calif.espanol := TRUNC(DBMS_RANDOM.VALUE(1,101));
            v_rec_calif.matematicas := TRUNC(DBMS_RANDOM.VALUE(1,101));
            v_rec_calif.sociales := TRUNC(DBMS_RANDOM.VALUE(1,101));
            v_rec_calif.naturales := TRUNC(DBMS_RANDOM.VALUE(1,101));
--
            INSERT INTO hr.calificaciones
            VALUES v_rec_calif;
        END LOOP;
--
        COMMIT;
    END LOOP;
END;
/*En este bloque anónimo nos valemos de la función VALUE del paquete RANDOM para insertar algunos registros en la tabla calificaciones, la lógica del SCRIPT es el siguiente: creamos una variable tipo Recordv_rec_calif con los campos de la tabla: calificaciones; usamos un FOR LOOP para generar los códigos de estudiantes (10) y otro LOOP FOR para generar 2 semestres por cada estudiante; y por último asignamos los valores generados por la función VALUE a los campos de la variable v_rec_calif  para su posterior inserción.*/
---
SELECT 
      cod_estudiante    AS estudiante,
      cod_semestre      AS semestre,
      espanol,
      matematicas,
      sociales,
      naturales,
      (espanol+matematicas+sociales+naturales)/AS promedio
FROM hr.calificaciones;
/*Consultamos la tabla para ver los registros insertados por el SCRIPT anterior.*/
---OUTPUT:
____________________________________________________________________________________
Fuentes: https://docs.oracle.com/cd/B28359_01/appdev.111/b28419/d_random.htm#ARPLS040

Compiladores SQL Online

Objetivos:
• Tener una herramienta auxiliar a la hora de hacer pruebas.

____________________________________________________________________________________
Editores SQL en la Web
En ocasiones necesitamos realizar un prueba con una sentencia/cláusula no familiar pero no tenemos una Base de Datos Oracle instalada en el ordenador que estamos usando. Como a mi personalmente me ha pasado, me di a la tarea de buscar y probar algunos de estos editores SQL para así poder compilar ciertos códigos de SQL y PL/SQL.

A continuación una lista de los que encontré con mejor funcionalidad:

Oracle Live SQLprovee un entorno de prueba para los usuarios de la Base de Datos Oracle. Esta plataforma presenta una forma sencilla de probar y compartir conceptos de desarrollo de aplicaciones SQL y PL/SQL en línea.

La misma le permite:
• Acceso a un esquema de Base de Datos Oracle con una hoja de cálculo SQL basado en el explorador.
 Posibilidad de guardar y compartir scripts SQL.
 Navegador de esquemas para ver y manejar los objectos de Base de Datos.
 Tutoriales educativos y interactivos.
 Ejemplos de acceso a datos personalizados para PL/SQL, Java, PHP y C.

Para tener acceso a esta herramienta solo necesita sus credenciales de Oracle Technology Network (OTN) y un interés en aprender SQL.

SCREENSHOTS:











Link de los SCRIPTs:
https://livesql.oracle.com/apex/livesql/file/content_D7VXIA1JNQ3BIMXNE6LNTE5C0.html
---
Oracle Application Express: permite diseñar, desarrollar e implementar Bellas y Sensibles aplicaciones que dependen de una Base de Datos utilizando únicamente su navegador web. 

SCREENSHOTS:





Para ver los detalles de lo que ofrece esta poderosa plataforma les invito a visitarla:
---
Tutorials PointEsta herramienta no solo provee permite desarrollar SQL en en Oracle, mas bien ofrece un amplio repertorio de editores y compiladores de los lenguajes mas utilizados en la actualidad. Su enfoque es el de proporcionar un medio educativo completo y accesible en todo momento.

El contenido y los recursos están disponibles gratuitamente, esto con el fin de incentivar a los lectores a adquirir tantas habilidades como deseen. Algo interesante es que no hay necesidad de registrarse o presentar datos personales para disfrutar de la plataforma.

SCREENSHOT:
---
SQLFiddle: Es un sitio web gratuito que puede utilizar para crear y guardar ejemplos de consultas de distintas Bases de Datos, con el fin de publicarlas en otros sitios web.

Suponga que desea ayuda con una consulta complicada y desea publicar la duda en un sitio Web XSQLFiddle le permite construir una Base de Datos modelo (esquema y datos) y por medio del enlace puede publicarlo en otras paginas.

SQLFiddle proporciona URL únicas para cada Base de Datos (y cada consulta); Sólo tienes que copiar y pegar la URL que quieres compartir, y estará disponible para cualquiera que quiera echar un vistazo.

SCREENSHOT:
---
W3Schools: es un popular sitio web para el aprendizaje de tecnologías web en línea. A parte de SQL incluye tutoriales y referencias relacionadas con HTML, CSS, JavaScript, PHP, Bootstrap y jQuery.

SCREENSHOT:
---
SQLiteOnline: Es otra plataforma de gestión de Bases de Datos relacional basada en SQLite que es una biblioteca que implementa un motor de Base de Datos SQL autónomo, transaccional, sin servidor y con cero configuración. El código para SQLite está en el dominio público y por lo tanto su uso es gratuito sin importar el propósito, comercial o privado.

SCREENSHOT:
____________________________________________________________________________________

sábado, 26 de noviembre de 2016

Funciones Analíticas en Oracle

Objetivos:
• Ampliar el repertorio de herramientas disponibles en Oracle.

NOTA: Usamos como ejemplo la Base de Datos: ORCL, la cual viene por defecto en cualquier versión de ORACLE.
____________________________________________________________________________________
Funciones Analíticas
Las funciones analíticas calculan un valor agregado basado en un grupo de filas. Una función analítica trabaja sobre varias filas y devuelve el resultado en la fila actual. Estas se diferencian de las funciones de grupo/agregadas en que las analíticas devuelven múltiples filas para cada grupo mientras que las grupales o agregadas retornan un valor por grupo.[1]

En Síntesis:
Una función agregada o grupal, agrega datos de varias filas en una sola, por lo cual, reduce el número de filas devueltas por la consulta. Por su parte las funciones analíticas funcionan en subconjuntos de filas, pero no reducen el número de filas devueltas por la consulta.

Las funciones analíticas son el último conjunto de operaciones realizadas en una consulta, a excepción de la cláusula ORDER BY, la cual va al final. Todas las combinaciones y todas las cláusulas WHERE, GROUP BY y HAVING se completan antes de procesar las funciones analíticas. Por lo tanto, las funciones analíticas sólo pueden aparecer en la lista de selección o en la cláusula ORDER BY.

Una función analítica podría ser a su vez una función grupal, como es el caso de COUNT RANK o una función analítica pura como NTILE.

Nota: No es posible anidar funciones analíticas especificando alguna en la cláusula analytic_clause. Sin embargo, puede especificar una función analítica en una subconsulta y usar otra función analítica sobre ella.

Sintaxis analytic_function:
analytic_function([ arguments ])
 OVER (analytic_clause)
---
Sintaxis analytic_clause:
[ query_partition_clause ]
[ order_by_clause [ windowing_clause ] ]
---
Sintaxis query_partition_clause:
PARTITION BY
  { value_expr[, value_expr ]...
  | ( value_expr[, value_expr ]... )
  }
---
Sintaxis order_by_clause:
ORDER [ SIBLINGS ] BY
{ expr | position | c_alias }
[ ASC | DESC ]
[ NULLS FIRST | NULLS LAST ]
  [, { expr | position | c_alias }
     [ ASC DESC ]
     [ NULLS FIRST | NULLS LAST ]
  ]...
---
Sintaxis windowing_clause:
{ ROWS | RANGE }
{ BETWEEN
  { UNBOUNDED PRECEDING
  | CURRENT ROW
  | value_expr { PRECEDING | FOLLOWING }
  } 
  AND
  { UNBOUNDED FOLLOWING
  | CURRENT ROW
  | value_expr { PRECEDING | FOLLOWING }
  }
| { UNBOUNDED PRECEDING
  | CURRENT ROW
  | value_expr PRECEDING
  }

}
---
Cláusula OVER:
El ámbito de una función analítica se define en una cláusula OVEROVER es una palabra clave obligatoria para todas las funciones analíticas. Dando () como parámetro, OVER indica el mayor alcance posible.

En términos simples, la cláusula OVER en Oracle especifica la partición o el orden en el que funcionará una función analítica.[2]

A continuación algunas Funciones Analíticas:

FIRST_VALUE: retorna el primer valor en un conjunto ordenado de valores. Si el primer valor del conjunto es nulo, la función devuelve NULL a menos que especifique IGNORE NULLS. Esta configuración es útil para la densificación de datos. Si especifica IGNORE NULLSFIRST_VALUE devuelve el primer valor no nulo en el conjunto, o NULL si todos los valores son nulos.


LAST_VALUE: Esta función funciona de la misma manera que FIRST_VALUE pero con el último valor de un conjunto ordenado de valores.

RANK: Como función analítica, calcula el rango de cada fila devuelta de una consulta con respecto a las otras filas retornadas.

ROW_NUMBER: Asigna un número único a cada fila a la que se aplica (ya sea cada fila de la partición o cada fila devuelta por la consulta), en la secuencia ordenada de filas especificada en el order_by_clause, comenzando por 1.

NTILE: Divide un conjunto de datos ordenados en la cantidad de cubos(buckets) indicados por el parámetro: expr y asigna el número de cubos apropiado a cada fila. Los cubos están numerados del 1 al valor expr. El valor expr debe ser a una constante positiva para cada partición. Oracle espera un número entero, y si expr es una constante NONINTEGER(no entera), Oracle trunca el valor a un entero. El valor de retorno es NUMBER.

Ejemplos:
SELECT
       department_id,
       COUNT(*)
            OVER (PARTITION BY  department_id) Total_Dept,
       job_id,
       COUNT(*)
            OVER (PARTITION BY job_id) Total_Job
FROM hr.employees;
/*Este ejemplo muestra como usar la función analítica COUNT; En el OUTPUT: cada resultado en la columna total_dept representa la cantidad de registros con el department_id en cuestión, mientras que la columna total_job es la cantidad de registros con la columna job_id en cuestión.*/
---OUTPUT:
SELECT
        last_name,
        salary,
        commission_pct,
        RANK()
            OVER (
                  PARTITION BY department_id
                    ORDER BY salary DESC, commission_pct DESC
                 ) "Rank"
FROM employees
WHERE department_id = 80;
/*El ejemplo  muestra como usar la función analítica RANK; Notar como la columna Rank asigna un rango o nivel a cada registro retornado, dándole prioridad a los registros con los salarios mas altos, notar que si los salarios son iguales se toma en cuenta la columna de la comisión y si esta es también igual, el rango seria el mismo.*/
---OUTPUT:
SELECT
       last_name,
       department_id,
       salary,
       FIRST_VALUE(salary) IGNORE NULLS 
         OVER (
                PARTITION BY department_id ORDER BY salary ASC
              ) AS lowest_in_dept
FROM    hr.employees;
/*Este ejemplo muestra como usar la función analítica FIRST_VALUE; Notar como la columna lowest_in_dept siempre muestra el primer salario por cada departamento de la lista, como la función esta ordenada por el salario de forma ascendente, el primer salario sera el mas bajo por cada departamento.*/
---OUTPUT:
SELECT
       last_name,
       department_id,
       salary,
       LAST_VALUE(salary) IGNORE NULLS 
         OVER (
                PARTITION BY department_id ORDER BY salary ASC
              ) AS highest_in_dept
FROM    hr.employees;
/*Contrario a la función FIRST_VALUE, LAST_VALUE muestra el último valor encontrado de la lista en cuestión, por esta razón el ejemplo se presta para mostrar el salario mas alto por cada departamento de la lista, ya que el mismo equivale al último valor de la lista ordenada por el salario en forma ascendente.*/
---OUTPUT:
SELECT
        department_id,
        last_name,
        employee_id,
        ROW_NUMBER()
            OVER (
                    PARTITION BY department_id ORDER BY employee_id ASC
                 ) AS emp_id
FROM    hr.employees;
/*El ejemplo muestra como usar la función analítica ROW_NUMBER; Notar que la columna emp_id muestra el orden o posición que representa el empleado en su departamento (ordenado por numero de empleado ascendente).*/
---OUTPUT:
SELECT
        last_name,
        salary,
        NTILE(4)
            OVER (ORDER BY salary DESC) AS quartile
FROM employees
WHERE department_id = 100;
/*El ejemplo muestra como usar la función analítica NTILE; La columna quartile equivale a la cantidad de cubos(buckets) asignada a cada registro ordenado por el salario en forma descendente dividido por 4.*/
---OUTPUT:



____________________________________________________________________________________
Fuentes: http://www.dba-oracle.com/t_over_analytic_function.htm
https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions001.htm#i81407

miércoles, 23 de noviembre de 2016

Las Pseudo-Columnas En Oracle

Objetivos:
• Tener un concepto claro sobre las pseudo-columnas de Oracle.
• Conocer los tipos de Pseudocolumnas en Oracle.
• Ver las Ventajas que Ofrecen.


NOTA: Usamos como ejemplo la Base de Datos: ORCL, la cual viene por defecto en cualquier versión de ORACLE.
____________________________________________________________________________________
Pseudocolumns
Las Pseudocolumnas se comportan como columnas reales en una tabla, aunque realmente no lo son. Pueden ser consideradas como elementos de datos de propósito especial que se pueden utilizar en sentencias SQL como si fueran parte de la tabla, pero no están contenidas en una tabla. Esencialmente, una pseudo-columna es un valor asignado de Oracle usado en el mismo contexto que una columna de Oracle, pero sin estar almacenada en el disco.[1]

Una pseudocolumna también es similar a una función sin argumentos. Sin embargo, las funciones sin argumentos típicamente devuelven el mismo valor para cada fila del conjunto de resultados, mientras que las pseudocolumnas normalmente devuelven un valor diferente para cada fila.[2]

Debe tener presente que si bien es posible seleccionar valores de una pseudocolumna, no es posible realizar operaciones DML tales como: INSERT INTO, UPDATE o DELETE sobre ellas.
____________________________________________________________________________________
Tipos de Pseudocolumnas
En Oracle existen un considerable número de Pseudocolumnas las cuales podrían clasificarse de acuerdo al contexto, a continuación presentamos un lista parcial de ellas:

Pseudocolumnas de Secuencias
Como ya sabemos, una secuencia es un objeto de esquema que puede generar valores secuenciales únicos. Estos valores se utilizan a menudo para claves primarias y únicas. Puede consultar valores de secuencia en sentencias SQL (En cualquier versión Oracle) y PL/SQL (11g en adelante) con estas pseudocolumnas:

NEXTVAL: Incrementa la secuencia y devuelve el siguiente valor.
CURRVAL: Devuelve el valor actual de una secuencia.

Ejemplos:
CREATE SEQUENCE sec_prueba
START WITH 1
INCREMENT BY 1
NOCYCLE;
/*Creamos la secuencia sec_prueba para a continuación usar las pseudocolumnas NEXTVAL y CURRVAL.*/
---
SELECT  sec_prueba.NEXTVAL
FROM dual;
/*Realizamos una simple consulta en la cual usamos la pseudocolumna NEXTVAL; Este ejemplo aplica a cualquier versión  Oracle.*/
---OUTPUT:
SELECT  sec_prueba.CURRVAL
FROM dual;
/*Realizamos una simple consulta en la cual usamos la pseudocolumna CURRVAL; Este ejemplo aplica a cualquier versión  Oracle.*/
---OUTPUT:
SET SERVEROUTPUT ON
DECLARE
    v_seq   NUMBER;
    v_date  DATE;
BEGIN
    v_seq   :=  sec_prueba.NEXTVAL;

    DBMS_OUTPUT.PUT_LINE('El valor generado es: '||v_seq);

    DBMS_OUTPUT.PUT_LINE('Valor actual: '||sec_prueba.CURRVAL);
END;
/*Este ejemplo muestra que es posible usar las pseudocolumnas NEXTVAL y CURRVAL en un bloque de PL/SQL(de 11g en adelante).*/
---OUTPUT:
Pseudocolumnas de Consulta de Versión/Version Query Pseudocolumns
Las pseudocolumnas de consulta de versión son válidas sólo en consultas de flashback de Oracle. A continuación una lista de ellas:

• VERSIONS_STARTTIME: Devuelve el TIMESTAMP de la primera versión de las filas devueltas por la consulta.

• VERSIONS_STARTSCN: Devuelve el SCN de la primera versión de las filas devueltas por la consulta.

• VERSIONS_ENDTIME: Devuelve el TIMESTAMP de la última versión de las filas devueltas por la consulta.

• VERSIONS_ENDSCN: Devuelve el SCN de la última versión de las filas devueltas por la consulta.

• VERSIONS_XID: para cada versión de cada fila, devuelve el ID (un número RAW) de la transacción que creó esa versión de fila.

• VERSIONS_OPERATION: Para cada versión de cada fila, devuelve un carácter que representa la operación que causó esa versión de fila. Los valores devueltos son I (para una operación de inserción), U (para una operación de actualización) o D (para una operación de borrado).

Ejemplos:
INSERT INTO hr.employees
                          (
                            employee_id,
                            last_name,
                            email,
                            hire_date,
                            job_id
                          )
VALUES
    (
      1111,
      'Aponte',
      'aponte@',
      SYSDATE,
      'IT_PROG'
    );
COMMIT;
/*Insertamos un nuevo registro en la tabla employees.*/
---
SELECT
      VERSIONS_STARTTIME,
      VERSIONS_STARTSCN,
      VERSIONS_ENDTIME,
      VERSIONS_ENDSCN,
      VERSIONS_XID,
      VERSIONS_OPERATION,
      employee_id,
      last_name,
      email
FROM hr.employees
VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE
WHERE employee_id = 1111;
/*Consultamos el nuevo registro insertado en la tabla employees; Notar que el registro con el  VERSIONS_STARTSCN = 5973562155948, en VERSIONS_OPERATION tiene: I (INSERT) y que VERSIONS_ENDTIME y VERSIONS_ENDSCN contienen valores nulos, esto porque este registro representa la ultima versión(No había sufrido cambios hasta ese momento).*/
---OUTPUT:
UPDATE hr.employees
SET last_name = 'Castillo'
WHERE employee_id = 1111;
COMMIT;
/*En este ejemplo procedemos a modificar el registro anteriormente insertado en la tabla employees; al volver a ejecutar la consulta, notamos lo siguiente: El anterior registro con el VERSIONS_STARTSCN = 5973562155948 ahora tiene valores en los campos: VERSIONS_ENDTIME VERSIONS_ENDSCN; El nuevo registro con el VERSIONS_STARTSCN 5973562155974 contiene: U (UPDATE) en VERSIONS_OPERATION  y su VERSIONS_ENDTIME VERSIONS_ENDSCN están nulos.*/
---OUTPUT:
Para más información acerca de las consultas flashback de Oracle hacer click aquí.

Pseudocolumna ROWID
Para cada fila de la Base de Datos, la pseudocolumna ROWID devuelve la dirección de la fila. Los valores ROWID de Oracle contienen la información necesaria para localizar una fila.

Normalmente, un valor ROWID identifica de forma única una fila en la Base de Datos. Sin embargo, las filas en tablas diferentes que se almacenan juntas en el mismo clúster pueden tener el mismo ROWID.

Los valores de la pseudocolumna ROWID tienen el tipo de datos ROWID o UROWID.

Entre los usos mas importantes de los ROWID podemos mencionar:
• Son la forma más rápida de acceder a una sola fila.
• Pueden mostrarle cómo se almacenan las filas de una tabla.
• Son identificadores únicos para filas en una tabla.
• No debe utilizar ROWID como clave principal de una tabla. Por ejemplo, si elimina y vuelve a insertar una fila con las utilidades de importación y exportación (Import and Export utilities), puede que su ROWID cambie. Si elimina una fila, Oracle puede reasignar su ROWID a una nueva fila insertada posteriormente.

Nota: si usas Toad for Oracle y ejecutas una consulta ordenando por el ROWID, puedes editar los valores en los campos de la tabla de forma manual en el Data Grid (ejemplo mas adelante).

Ejemplos:
DECLARE
    v_max_emp   NUMBER;

    CURSOR c_max_emp IS
        SELECT MAX(employee_id)
        FROM hr.employees;
BEGIN
    OPEN c_max_emp;
    FETCH c_max_emp INTO v_max_emp;
    CLOSE c_max_emp;

    FOR i IN 1..5 LOOP
        v_max_emp :=  v_max_emp+i;

        INSERT INTO hr.employees
                                  (
                                    employee_id,
                                    last_name,
                                    email,
                                    hire_date,
                                    job_id
                                  )
        VALUES
            (
              v_max_emp,
              'Emp '||i,
              'correo'||i||'@',
              SYSDATE,
              'IT_PROG'
            );
    END LOOP;

    COMMIT;
END;
/*Con este Bloque de PL/SQL procedemos a insertar 5 registros mas en la tabla employees.*/
---
SELECT
      ROWID,
      employee_id,
      last_name,
      email
FROM hr.employees
WHERE employee_id > 1111;
/*Consultamos los empleados insertados en el ejemplo anterior para así notar cada ROWID.*/
---OUTPUT:
SELECT  *
FROM hr.employees
WHERE employee_id = 1111
ORDER BY ROWID;
/*Consultamos el registro insertado en ejemplos anteriores y ordenamos la consulta por el ROWID para así poder editar los datos directamente desde el Data Grid (solo en Toad for Oracle)*/
---OUTPUT:
Pseudocolumna ROWNUM
Para cada fila devuelta por una consulta, la pseudocolumna ROWNUM devuelve un número que indica el orden en que Oracle selecciona la fila de una tabla o conjunto de filas unidas. La primera fila seleccionada tiene un ROWNUM de 1, el segundo tiene 2, y así sucesivamente.

Ejemplos:
SELECT
      ROWNUM,
      employee_id,
      last_name,
      email
FROM hr.employees
WHERE employee_id > 1110;
/*Consultamos los registros que hemos insertado recientemente; Notar como se muestra el ROWNUM de cada linea.*/
---OUTPUT:
SELECT
      ROWNUM,
      employee_id,
      last_name,
      email
FROM hr.employees
WHERE employee_id > 1110
AND ROWNUM < 4;
/*Este ejemplo muestra que es posible usar la pseudocolumna ROWNUM en la cláusula WHERE de una consulta.*/
---OUTPUT:
Pseudocolumnas de consultas jerárquicas
Para más información acerca de las consultas Consultas Jerárquicas de Oracle hacer click aquí.

Pseudocolumna LEVEL
Para cada fila devuelta por una consulta jerárquica, la pseudocolumna LEVEL devuelve 1 para una fila raíz, 2 para un hijo de una raíz, y así sucesivamente. Una fila raíz es la fila más alta dentro de un árbol invertido. Una fila secundaria es cualquier fila no raíz. Una fila principal es cualquier fila que tiene hijos. Una hilera de hojas es cualquier hilera sin hijos.

Tenga en cuenta que es posible usar la pseudocolumna LEVEL en consultas normales, no solo en consultas jerárquicas. A continuación un ejemplo:

SELECT
        LEVEL,
        CASE
            WHEN LEVEL > 4 THEN 'ALTO'
            WHEN LEVEL < 3 THEN 'BAJO'
            ELSE 'MEDIO'
        END AS consideración
FROM dual
CONNECT BY LEVEL <= 5
ORDER BY LEVEL DESC;
/**/
---OUTPUT:
____________________________________________________________________________________
Para una lista Detallada de las pseudocolumna s de Oracle seguir el siguiente Link:
Fuentes: https://docs.oracle.com/cd/B19306_01/server.102/b14200/pseudocolumns.htm