jueves, 3 de junio de 2021

Querying DBA_JOBS encounter ORA-01873

En la versión de Oracle 19c se me presentó error al tratar de realizar la consulta haca la vista DBA_JOBS.

select * from dba_jobs;
ORA-01873: the leading precision of the interval is too small


Revisando en la documentación de Oracle "Querying DBA_JOBS Encounter ORA-01873 (Doc ID 2710794.1)" se indica que


CAUSA:

Lista de verificación de la herramienta de actualización previa de la base de datos. (ID de documento 2380601.1)A partir de Oracle Database 19c, los trabajos creados y administrados a través del paquete DBMS_JOB en versiones anteriores de la base de datosse volverán a crear utilizando la arquitectura Oracle Scheduler. Es posible que los trabajos que no se hayan vuelto a crear correctamente no funcionen correctamente después de la actualización.

SOLUCION

Ignore la columna TOTAL_TIME y seleccione otras columnas para obtener la información de la consulta DBA_JOBS.

O

Consultando dba_scheduler_jobs y verá todos los trabajos  que fueron creados usando dbms_job. 
select *  from dba_scheduler_jobs;


Como vemos la solución esta en omitir de la consulta el campo TOTAL_TIME de la vista DBA_JOBS o usar DBA_SCHEDULER_JOBS.

Como en mi caso esta solución no me ayudaba de mucho por que no pdodia editar el programa que hacia uso de esa vista lo que realice es editar la vista DBA_JOBS. Si ya se que me diran que no debemos hacaerlo ya que es un objeto del SYS, pero les comento que no todo esta escrito en piedra asi que lo hice y me funcionó.

Deben de conectarse con el SYS para poder realizar la modificación.

CREATE OR REPLACE FORCE VIEW SYS.DBA_JOBS
(
   JOB,
   LOG_USER,
   PRIV_USER,
   SCHEMA_USER,
   LAST_DATE,
   LAST_SEC,
   THIS_DATE,
   THIS_SEC,
   NEXT_DATE,
   NEXT_SEC,
   TOTAL_TIME,
   BROKEN,
   INTERVAL,
   FAILURES,
   WHAT,
   NLS_ENV,
   MISC_ENV,
   INSTANCE
)
   BEQUEATH DEFINER AS
   SELECT m.dbms_job_number                                                                JOB,
          j.creator                                                                        LOG_USER,
          u.name                                                                           PRIV_USER,
          u.name                                                                           SCHEMA_USER,
          j.last_start_date                                                                LAST_DATE,
          SUBSTR ( TO_CHAR ( j.last_start_date, 'HH24:MI:SS' ), 1, 8 )                     LAST_SEC,
          DECODE ( BITAND ( j.job_status, 2 ), 2, j.last_start_date, NULL )                THIS_DATE,
          DECODE ( BITAND ( j.job_status, 2 ), 2, SUBSTR ( TO_CHAR ( j.last_start_date, 'HH24:MI:SS' ), 1, 8 ), NULL )
             THIS_SEC,
          j.next_run_date                                                                  NEXT_DATE,
          SUBSTR ( TO_CHAR ( j.next_run_date, 'HH24:MI:SS' ), 1, 8 )                       NEXT_SEC,
          ( CASE
              WHEN j.last_end_date > j.last_start_date THEN
                 --EXTRACT (
                 --DAY FROM (j.last_end_date - j.last_start_date) * 86400)
          (CAST(j.last_end_date AS DATE)-CAST(j.last_start_date AS DATE)) * 86400
              ELSE
                 0
           END )
             TOTAL_TIME,                                                          -- Scheduler does not track total time
          DECODE ( BITAND ( j.job_status, 1 ), 0, 'Y', 'N' )                               BROKEN,
          DECODE ( BITAND ( j.flags, 1024 + 4096 + 134217728 ), 0, j.schedule_expr, NULL ) INTERVAL,
          j.failure_count                                                                  FAILURES,
          j.program_action                                                                 WHAT,
          j.nls_env                                                                        NLS_ENV,
          j.env                                                                            MISC_ENV,
          NVL ( j.instance_id, 0 )                                                         INSTANCE
     FROM sys.scheduler$_dbmsjob_map m
          LEFT OUTER JOIN sys.obj$ o ON ( o.name = m.job_name )
          LEFT OUTER JOIN sys.user$ u ON ( u.name = m.job_owner )
          LEFT OUTER JOIN sys.scheduler$_job j ON ( j.obj# = o.obj# )
    WHERE o.owner# = u.user#;

Se marca con rojo lo que viene por defecto y genera el error y se marca con azul con lo que se remplazó y funcionó.


Espero les sirva.

lunes, 3 de mayo de 2021

DBMS_FILE_TRANSFER - Copiar archivos binarios en la base de datos y entre bases de datos por medio de DBLINK

Introducido desde la versión 10g DBMS_FILE_TRANSFER es una API que nos permite realizar copiados de archivos binario dentro de la base de datos y/o entre base de datos Oracle si necesidad de comandos del sistema operativo.

Estos nos facilita tarea de copiado de archivos en la base o entre base sin tener que ingresar a un cmd o ssh.

Consideraciones

  • Hay tener en cuenta que cuando digo archivos binarios me refiero a : Datafiles, Controlfiles, Redologs, Archivelogs, Backups, Exports DMP, ect.
  • Los archivos copiado deben de tener tamaño multiple de 512 bytes.
  • El archivo a copiar debe de ser menor o igual a 2Tb.
  • El usuario debe tener privilegios de lectura en el objeto del directorio de origen y privilegios de escritura en el objeto del directorio de destino.
Procedimientos disponible:
  • COPY_FILE (Local a Local)Lee un archivo local y crea una copia del mismo en el sistema de archivos local, es decir en el mimo servidor.
  • GET_FILE(De Remota a Local) Conecta con una base de datos remota por medio de un DBLINK para leer un archivo remoto y luego crea una copia del archivo en el sistema de archivos local.
  • PUT_FILE(De una Local a Remota) Lee un archivo local y contacta con una base de datos remota por medio de un DBLINK para crear una copia del archivo en el sistema de archivos remoto.

Procedimiento COPY_FILE
Copiado de archivos en el mismo servidor.
Sintaxis
DBMS_FILE_TRANSFER.COPY_FILE(
                               source_directory_object       IN  VARCHAR2,
                               source_file_name              IN  VARCHAR2,
                               destination_directory_object  IN  VARCHAR2,
                               destination_file_name         IN  VARCHAR2);

ParámetroDescripción

source_directory_object

El objeto de directorio desde el que se copia el archivo en el sistema

 de archivos local. Este objeto de directorio debe existir.

source_file_name

El nombre del archivo que se copia en el sistema de archivos local. 

Este archivo debe existir en el sistema de archivos local en el

 directorio asociado con el objeto del directorio de origen.

destination_directory_object

El objeto de directorio en el que se coloca el archivo en el sistema de

 archivos local. Este objeto de directorio debe existir en el sistema de

 archivos local.

destination_file_name

El nombre del archivo copiado en el objeto de directorio de destino en

 el sistema de archivos local. Un archivo con el mismo nombre no

 debe existir en el directorio de destino del sistema de archivos local.

Ejemplo
--Copiar EXPFULLDB.DMP de la ruta /u01/oradmp/ a /u02/oradmp/
-- Crear directorios para el copiado de un archivo DMP.
CREATE OR REPLACE DIRECTORY dmp_files_dir1 AS '/u01/oradmp/';
CREATE OR REPLACE DIRECTORY dmp_files_dir2 AS '/u02/oradmp/';

-- Copiar
BEGIN
  DBMS_FILE_TRANSFER.copy_file(
   source_directory_object      => 'DMP_FILES_DIR1',--Directorio Origen
   source_file_name             => 'EXPFULLDB.DMP',--Archivo origen a copiar
   destination_directory_object => 'DMP_FILES_DIR2',--Directorio destino
   destination_file_name        => 'EXPFULLDB.DMP'/*Nombre archivo destino*/);
END; /

Procedimiento GET_FILE
Copiado de archivos desde una base remota hacia la local.
Sintaxis
DBMS_FILE_TRANSFER.GET_FILE(
                           source_directory_object IN VARCHAR2,    
                           source_file_name IN VARCHAR2,  
                           source_database IN VARCHAR2,  
                           destination_directory_object IN VARCHAR2,
                        destination_file_name IN VARCHAR2);
ParámetroDescripción

source_directory_object

El objeto de directorio desde el que se copia el archivo en el sitio de

 origen. Este objeto de directorio debe existir en el sitio de origen.

source_file_name

El nombre del archivo que se copia en el sistema de archivos

 remoto. Este archivo debe existir en el sistema de archivos remoto en

 el directorio asociado con el objeto del directorio de origen.

source_database

El nombre de un enlace de base de datos a la base de datos remota

 (DBLINK) donde se encuentra el archivo.

destination_directory_object

El objeto de directorio en el que se coloca el archivo en el sitio de

 destino. Este objeto de directorio debe existir en el sistema de

 archivos local.

destination_file_name

El nombre del archivo copiado en el sistema de archivos local. Un

 archivo con el mismo nombre no debe existir en el directorio de

 destino del sistema de archivos local.


Ejemplo.
Desde la base de datos ORCL01 vamos a traer desde la base de datos Remota ORCL02 instanciada con el DBLINK DBL_ORCL02 el archivo de EXPDP_FULL_ORCL02.DMP. El archivo a traer se encuentra en el directorio DATA_PUMP_DIR y lo vamos a copiar en el mismo directorio directorio de la base de datos local.
- Vamos a copiar un DMP desde una base de datos remota hacia la base de datos Local.
- Consigue el archivo.
BEGIN
  DBMS_FILE_TRANSFER.get_file (
   source_directory_object => 'DATA_PUMP_DIR'/*Directorio origen base remota*/,
   source_file_name => 'EXPDP_FULL_ORCL02.DMP'/*Nombre del DMP remoto a descargar*/,
   source_database => 'DBL_ORCL02' /*DBlink de la base de datos remota*/,
   destination_directory_object  => 'DATA_PUMP_DIR'/*Directorio destino local de la base*/,
destination_file_name => 'EXPDP_FULL_ORCL02.DMP'/*Nombre del DMP destino*/);
END; /

Procedimiento PUT_FILE
Copiado des archivos desde una base local hacia una base de datos remota.
Sintaxis
DBMS_FILE_TRANSFER.PUT_FILE (
                               source_directory_object IN VARCHAR2,   
                               source_file_name IN VARCHAR2,
                               destination_directory_object IN VARCHAR2,
                               destination_file_name IN VARCHAR2,  
                               destination_database IN VARCHAR2);
ParámetroDescripción

source_directory_object

El objeto de directorio desde el que se copia el archivo en el sitio de

 origen local. Este objeto de directorio debe existir en el sitio de

 origen.

source_file_name

El nombre del archivo que se copia del sistema de archivos local. Este

 archivo debe existir en el sistema de archivos local en el directorio

 asociado con el objeto del directorio de origen.

destination_directory_object

El objeto de directorio en el que se coloca el archivo en el sitio de

 destino. Este objeto de directorio debe existir en el sistema de

 archivos remoto.

destination_file_name

El nombre del archivo colocado en el sistema de archivos remoto. Un

 archivo con el mismo nombre no debe existir en el directorio de

 destino del sistema de archivos remoto.

destination_database

El nombre de un enlace de base de datos a la base de datos remota en

 la que se copia el archivo.


Ejemplo
Desde la base de datos ORCL01 vamos a enviar el archivo EXPDP_FULL_ORCL01.DMP a una la base de datos Remota ORCL02 instanciada con el DBLINK DBL_ORCL02 . El archivo a enviar se encuentra en el directorio DATA_PUMP_DIR y lo vamos a copiar en el mismo directorio directorio de la base de datos local.
-- Vamos a copiar desde la base de datos local ORCL01 el archivo EXPDP_FULL_ORCL02.DMP
-- y enviarlo a la base de datos remota ORCL02 por medio del DBLINK DBL_ORCL02.

BEGIN
  DBMS_FILE_TRANSFER.put_file (
   source_directory_object => 'DATA_PUMP_DIR'/*Directorio origen local*/,
   source_file_name => 'EXPDP_FULL_ORCL01.DMP'/*Archivo origen local*/,
destination_directory_object => 'DATA_PUMP_DIR'/*Directorio destino remoto*/,
destination_file_name => 'EXPDP_FULL_ORCL01.DMP'/*Archivo destino remoto*/,
destination_database => 'DBL_ORCL02'/*DBLINK*/); END;/

Listo, ya vimos las tres forma de usar DBMS_FILE_TRANSFER, solo te toca ver cual se adapta a tu necesidad.


martes, 27 de abril de 2021

Leer datos JSON como Tabla en Oracle - JSON_TABLE

Hola, en un post anterior hable de como extraer información de un dato con formato JSON con la función JSON_VALUE, ahora les quiero mostrar como tratar el formato JSON como si fuera una tabla. JSON_TABLE es una función que viene disponible desde la version 12.1.0.2

Para entenderlo mejor veámoslo con un ejemplo practico, vamos a tener una lista de personas Nombre, Sexo , Edad y Email. 

Para esto vamos a simular que el dato JSON esta en una tabla JSON_DATO con la clausula WITH .

WITH JSON_DATO AS
(
    SELECT '[   {Nombre:"Victor", Sexo:"M", Edad:30}, 
                {Nombre:"Manuel", Sexo:"M", Edad:25}, 
                {Nombre:"Paola" , Sexo:"F", Edad:30} ]' AS JSON_PERSONAS
    FROM DUAL
)
select Personas.*
from JSON_DATO,
JSON_TABLE (JSON_PERSONAS, '$[*]
            COLUMNS (   Nombre VARCHAR2 (50) PATH '$.Nombre',
                        Sexo   VARCHAR2 (1 ) PATH '$.Sexo',
                        Edad   NUMBER   (3 ) PATH '$.Edad') 
           )AS Personas;





Este ejemplo tiene el mismo resultado que el anterior, sino que se agrega en el JSON elemento de lista Persona para que vean como varia la ruta de acceso al dato

WITH JSON_DATO AS
(
    SELECT '[   {Persona:[{Nombre:"Victor", Sexo:"M", Edad:30}]}, 
                {Persona:[{Nombre:"Manuel", Sexo:"M", Edad:25}]}, 
                {Persona:[{Nombre:"Paola" , Sexo:"F", Edad:30}]} ]' AS JSON_PERSONAS
    FROM DUAL
)
select Personas.*
from JSON_DATO,
JSON_TABLE(JSON_PERSONAS, '$.Persona[*]
           COLUMNS ( Nombre VARCHAR2 (50) PATH '$.Nombre',
                     Sexo   VARCHAR2 (1 ) PATH '$.Sexo',
                     Edad   NUMBER   (3 ) PATH '$.Edad') 
          )AS Personas;





Incluyamos un elemento de dirección que contenga datos de la ubicación. Fíjense en las rutas de acceso como es para acceder al dato dirección.

WITH JSON_DATO AS
(
    SELECT 
    '[  {Persona:[{Nombre:"Victor", Sexo:"M", Edad:30, 
                   Dir:{Pais:"ECU", Ciu:"GYE"} }]
                  }, 
        {Persona:[{Nombre:"Manuel", Sexo:"M", Edad:25, 
                   Dir:{Pais:"ECU", Ciu:"QTO"} }]
                  }, 
        {Persona:[{Nombre:"Paola" , Sexo:"F", Edad:30, 
                   Dir:{Pais:"COL", Ciu:"BOG"} }]
                 
     ]' 
            AS JSON_PERSONAS
    FROM DUAL
)
select Personas.*
from JSON_DATO,
JSON_TABLE(JSON_PERSONAS, '$.Persona[*]
            COLUMNS (   Nombre VARCHAR2 (50) PATH '$.Nombre',
                        Sexo   VARCHAR2 (1 ) PATH '$.Sexo',
                        Edad   NUMBER   (3 ) PATH '$.Edad',
                        Pais   VARCHAR2 (10) PATH '$.Dir.Pais',
                        Ciudad VARCHAR2 (10) PATH '$.Dir.Ciu') 
         )AS Personas;




Ahora para hacerlo mas interesante vamos a incluir un elemento de Fono que puede tener ninguno o varios numero de teléfonos. Para esto vamos a usar la clausula NESTED PATH para poder acceder a la lista de telefonos que esta dentro del elemento Fono.

WITH JSON_DATO AS
(
    SELECT 
    '[  {Persona:[{Nombre:"Victor", Sexo:"M", Edad:30, 
                   Dir:{Pais:"ECU", Ciu:"GYE"}, 
                   Fono:[{Tipo:"Mobil",Numero:"555-444"},
                         {Tipo:"Casa",Numero:"555-000"}]}]
        }, 
        {Persona:[{Nombre:"Manuel", Sexo:"M", Edad:25, 
                   Dir:{Pais:"ECU", Ciu:"QTO"} }]
        }, 
        {Persona:[{Nombre:"Paola" , Sexo:"F", Edad:30, 
                   Dir:{Pais:"COL", Ciu:"BOG"},
                   Fono:[{Tipo:"Casa",Numero:"333-000"}] }]
        } 
     ]' 
            AS JSON_PERSONAS
    FROM DUAL
)
select Personas.*
from JSON_DATO,
JSON_TABLE(JSON_PERSONAS, '$.Persona[*]' 
            COLUMNS (   Nombre VARCHAR2 (50) PATH '$.Nombre',
                        Sexo   VARCHAR2 (1 ) PATH '$.Sexo',
                        Edad   NUMBER   (3 ) PATH '$.Edad',
                        Pais   VARCHAR2 (10) PATH '$.Dir.Pais',
                        Ciudad VARCHAR2 (10) PATH '$.Dir.Ciu',
                        NESTED PATH '$.Fono[*]'
                            COLUMNS (FonoTipo VARCHAR2(32) PATH '$.Tipo',
                                     FonoNumero VARCHAR2(32) PATH '$.Numero')
                    ) 
         )AS Personas;


Listo, ya tenemos un dato JSON como tabla, espero les sirva!!

Leer datos con formato JSON desde Oracle - JSON_VALUE

Si necesitamos realizar alguna operación con datos que tengan formato JSON en versiones anteriores  a la 12c  hemos tenido que crear nuestras rutinas para leer los datos de este formato, pero ahora desde la version Oracle 12.1.0.2 ya se incluyó utilidades para extrae los datos como JSON_VALUE el cual es una gran utilidad.

JSON_VALUE como primer parámetro recibe la cadena de JSON y segundo la ruta o dirección dé extracción del dato.




Ejemplos

Para un entendimiento practico vamos a realizar un ejemplo, Empecemos con algo básico extraigamos dato Color

SELECT JSON_VALUE('{Color:"Amarillo"}', '$.Color') AS value 
FROM DUAL;




Ahora con varios colores, fijemos del lado de la ruta indicamos el elemento "Color2" para que nos retorne el color.

SELECT JSON_VALUE('{Color1:"Amarillo", Color2:"Azul", Color2:"Rojo"}', '$.Color2') AS value 
FROM DUAL;




Extrae elemento de la lista basado en el índice del elemento, las posiciones de los elementos van desde 0 hasta 2

SELECT JSON_VALUE('["Amarillo", "Azul", "Rojo"]', '$[2]') AS value 
FROM DUAL;



Extraer una propiedad de uno de los elementos de la lista

SELECT JSON_VALUE('[{Color:"Amarillo"}, {Color:"Azul"}, {Color:"Rojo"}]', '$[1].Color') AS value 
FROM DUAL;




Ahora veamos algo mas practico, tendremos una lista de personas Nombre, Sexo y Edad. Para hacer esto el dato JSON  lo voy a poner en una subconsulta y el elemento que extraeré es el de la tercera posición (para el arreglo va a ser la 2).

SELECT  JSON_VALUE(A.DATO_JSON,'$[2].Nombre')   Nombre, 
        JSON_VALUE(A.DATO_JSON,'$[2].Sexo')     Sexo, 
        JSON_VALUE(A.DATO_JSON,'$[2].Edad')     Edad
FROM(
    SELECT '[   {Nombre:"Victor", Sexo:"M", Edad:30}, 
                {Nombre:"Manuel", Sexo:"M", Edad:25}, 
                {Nombre:"Paola" , Sexo:"F", Edad:30} ]' DATO_JSON
    FROM DUAL
)A;



Ahora agreguemos un campo mas "Email" en el dato JSON, pero que "Paola" no lo tenga para ver el resultado . 

SELECT  JSON_VALUE(A.DATO_JSON,'$[2].Nombre')   Nombre, 
        JSON_VALUE(A.DATO_JSON,'$[2].Sexo')     Sexo, 
        JSON_VALUE(A.DATO_JSON,'$[2].Edad')     Edad,
        JSON_VALUE(A.DATO_JSON,'$[2].Email')    Email
FROM(
    SELECT '[   {Nombre:"Victor", Sexo:"M", Edad:30, Email:"victor@hola.com"}, 
                {Nombre:"Manuel", Sexo:"M", Edad:25, Email:"manuel@hola.com"}, 
                {Nombre:"Paola" , Sexo:"F", Edad:30} ]' DATO_JSON
    FROM DUAL
)A;



Lo que ocurrió es que aunque el el campo no exista lo va a presentar NULO. Tambien podemos manejo eventos de datos nulos o errores para que en caso de que ocurra presente un default.

SELECT  JSON_VALUE(A.DATO_JSON,'$[2].Nombre')   Nombre, 
        JSON_VALUE(A.DATO_JSON,'$[2].Sexo')     Sexo, 
        JSON_VALUE(A.DATO_JSON,'$[2].Edad')     Edad,
        JSON_VALUE(A.DATO_JSON,'$[2].Email' DEFAULT 'No definido' ON ERROR)    Email
FROM(
    SELECT '[   {Nombre:"Victor", Sexo:"M", Edad:30, Email:"victor@hola.com"}, 
                {Nombre:"Manuel", Sexo:"M", Edad:25, Email:"manuel@hola.com"}, 
                {Nombre:"Paola" , Sexo:"F", Edad:30} ]' DATO_JSON
    FROM DUAL
)A;



Espero les sirva de ayuda


martes, 2 de junio de 2020

Lectura de datos de un XML Oracle.

Como podemos dar lectura a los datos de un XML, bueno para esto vamos hacer uso de funciones propias de Oacle para lograr este objetivo.

Veamos el caso con un ejemplo, tenemos un XML con datos de paises, vemos que como primer elemento esta <datos> y como elementos hijos están los países y con los países lo datos relacionados(id, cod, nombre). Dentro del dato hay dos pisases.

<datos>
    <pais>
        <id>1</id>
        <cod>ECU</cod>
        <nombre>Ecuador</nombre>
    </pais>
    <pais>
        <id>2</id>
        <cod>COL</cod>
        <nombre>Colombia</nombre>
    </pais>
</datos>
 
El formato XML lo vamos a tranformar en una estructura que permita tratarlo como una tabla y con ello podamos realizar consultas.


SELECT * 
FROM TABLE (XMLSEQUENCE (EXTRACT (XMLTYPE.CREATEXML (
'<datos>
    <pais>
        <id>1</id>
        <cod>ECU</cod>
        <nombre>Ecuador</nombre>
    </pais>
    <pais>
        <id>2</id>
        <cod>COL</cod>
        <nombre>Colombia</nombre>
    </pais>
</datos>'                                   ), '/'))) PAIS


Si ejecutamos el sql solo nos devolverá un solo registro con el campo COLUMN_VALUE con el formato XML.

Antes de avanzar para ver como recorrer los registro que conforman el XML primero les explicaré como fue que se armo la consulta con las funciones utilizadas del lado del from.

  • XMLTYPE.CREATEXML Convierte texto con formato XML en un tipo de dato XML. Utilizamos el XML de países de ejemplo.
  • EXTRACT Extraemos los elementos del XML en el nivel /, todo el XML.
  • XMLSEQUENCE Extrae los nodos dentro del XML.
  • TABLE Transforma en tabla los resultados del XMLSEQUENCE.
Ahora  si, ya explicado las funciones del lado del from vamos a obtener  cada uno de los registro de país. Para ellos vamos a indicar en el EXTRACT el parametro '/datos/pais' para que así recorramos todos los elementos de país.

SELECT * 
FROM TABLE (XMLSEQUENCE (EXTRACT (XMLTYPE.CREATEXML (
'<datos>
    <pais>
        <id>1</id>
        <cod>ECU</cod>
        <nombre>Ecuador</nombre>
    </pais>
    <pais>
        <id>2</id>
        <cod>COL</cod>
        <nombre>Colombia</nombre>
    </pais>
</datos>'                                   ), '/datos/pais'))) PAIS


El resultado sera todos los elementos de pais, pero todavía nos falta obtener el dato de cada campo de país, para ello vamos a usar la función ExtractValue para obtener cada uno de los campos del registro.

SELECT  ExtractValue(Value(PAIS),'/pais/id/text()')id
       ,ExtractValue(Value(PAIS),'/pais/cod/text()')cod 
       ,ExtractValue(Value(PAIS),'/pais/nombre/text()')nombre 
FROM TABLE (XMLSEQUENCE (EXTRACT (XMLTYPE.CREATEXML (
'<datos>
    <pais>
        <id>1</id>
        <cod>ECU</cod>
        <nombre>Ecuador</nombre>
    </pais>
    <pais>
        <id>2</id>
        <cod>COL</cod>
        <nombre>Colombia</nombre>
    </pais>
</datos>'                                   ), '/datos/pais'))) PAIS



Nota:
XMLSEQUENCE  es una función que se uso desde la versión 10g  y sigue funcionando en versiones superiores pero en la versión 11g se incluyó la XMLTable  como una mejora.



viernes, 5 de julio de 2019

Creacion de una base de datos Oracle como plataforma PaaS en Amazona AWS RDS

Dentro de los productos que ofrece Amazon en su plataforma AWS esta el servicio  de base de datos relacionales RDS.

Así como otros proveedores de cloud Amazon ofrece de forma gratuita 750 horas para acceder a los productos y probarlos.

Hoy vamos a crear una base de datos en el RDS, que es un PaaS (Plataforma como servicio) en el cloud de Amazon.

Lo primero que tienes que hacer es registrarte en el siguiente link:

Aquí necesitaras de proporcionar una tarjeta de crédito donde solo te debitaran $1 dolarito solo como confirmación de que la tarjeta es valida, no se te cobrar nada mas adicional en la que Amazon mo te especifique, ademas debes de especificar como deseas que te llegue el código de confirmación necesario para la activación de la cuenta por medio de SMS o llamada telefónica.

Una vez creado la cuenta empezaremos con la prueba.

1 Acceder a AWS




2 Buscar servicio RDS


3 Ir a la sección de Database y damos click en crear
Crear Database


4 Seleccionamos cada unos de los parámetros para la creación
Seleccionamos el motor de base de datos Oracle. Vemos que hay otros motores de base de datos conocidos.


Vamos a crear una edición enterprise


Seleccionaremos un template GRATIS, para que sea sin costo.


Especificamos el nombre de la base , usuario DBA y contraseña



Establecemos el CPU y la RAM, como es la opción gratis es la mas básica.


Definición de almacenamiento

En opción gratis no tenemos la opción de replica para contingencia

Configuración de Red


Tendremos que definir que sea publica para conectarnos fuera de la red del AWS


Podemos cambiar el juego de caracteres o definir otro grupo de configuración. Los grupos de configuración son parámetros de base de datos preestablecidos pero podemos crear unos personalizados.


Establecemos las políticas de backups


Activación del Inside, herramienta de captura de datos del rendimiento de host o base de datos


Establece configuraciones del cloudwach de acceso a los logs de base de datos y definición de los planes de mantenimiento.


Listo ahora si a crea, no preocupes el valor que esta ahí es un estimado de cuanto te costaría pero en version gratis no se cobrará.


Esperamos a que se termine el despliegue que demorará unos minutos.





5 Conectarnos a la base de datos.

Primero debemos configura la VPC que no es mas que el firewall, en este ejemplo daremos un acceso total a las conexiones inbound, com dije es de prueba y solo para prueba daremos este acceso, de ahí en un esquema productivo deberemos dar los acceso a las ip o segmentos requeridos de manera consensuada ya que estamos exponiendo al mundo entero la base de datos y en un entorno de de producción es inaceptable dar este permio.

No vamos al VPC y seleccionamo el grupo que asignamos a la base

En la sección inbound editamos la regla y creamos al all trafic a Anywhere(Como dije es prueba y solo a pruaba daremos este permiso), tambien podemos dar el permiso por ip o servicio RDS



Vemos los datos de configuración de la base de datos para armar nuestro string de conexión

HOST:orcltest.cohkyuv02cj3.us-west-2.rds.amazonaws.com
BD:ORCLTEST
LISTENER:1521

Con estos datos armamos nuestra cadena de conexión para el sqlplus:

admin@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=orcltest.cohkyuv02cj3.us-west-2.rds.amazonaws.com)(PORT=1521))(CONNECT_DATA=(SID=orcltest)))

Listo en el SQLPLUS conectarnos con la cadena de conexión




Habemos Database RDS!!!