Archivo de la etiqueta: DBLINK

Crear una tabla con contenido mediante database link de una base de datos a otra

En la siguiente entrada de Blog, voy a explicar como crear una tabla con contenido en una base de datos Oracle accediendo a otra base de datos Oracle mediante un database Link. Además voy a mostrar que la creación de la tabla en destino puede presentar diferencias de storage dependiendo de cómo la creemos. Si queremos que sea idéntica a la de origen, tendremos que copiar sus parámetros de storage en la sentencia de creación. Esto es una manera de crear una tabla con contenido sin necesidad de utilizar las utilidades exp/imp ni expdp/impdp.

Esto es muy útil cuando queremos crear una tabla que tenemos en Desarrollo o Pre-producción y queremos pasarlo al entorno de producción.

Para el ejemplo daré por hecho que tenemos un Data Base Link creado que permite acceder a la Base de datos de destino. Un database link se crea de la siguiente manera:

CREATE PUBLIC DATABASE LINK "MY_DBLINK"
CONNECT TO USUARIO_PRUEBA
IDENTIFIED BY  "<pwd_usuario>"
USING '<cadena_conexión>'; -- Esto consiste en una cadena de conexión que debe estar en tnsnames.ora

Puedes ampliar información sobre DBLinks aqui

Para comprobar que el DBLink funciona, podemos hacer la consulta hacia la tabla que queremos copiar de la siguiente  manera:

SQL> SELECT * FROM USUARIO_PRUEBA.TABLA@MY_DBLINK;

 Ahora creamos la tabla con el contenido de la siguiente manera:

- Primero nos conectamos a la Base de datos, con el usuario que corresponda, donde queremos crear la tabla con el contenido:

sqlplus usuario_prueba@cadena_conexion

- Ahora creamos la tabla …

SQL> CREATE TABLE usuario_prueba.nombre_tabla AS SELECT * from USUARIO_PRUEBA.TABLA@MY_DBLINK;

Esta sentencia creará la tabla en el destino con su contenido, pero los parámetros de STORAGE serán los que tenga el tablespace donde esta asignado “usuario_prueba”. Es decir, no cogerá los valores de STORAGE que tiene la tabla en origen.

Ahora probaremos con otro ejemplo, donde si detallamos el STORAGE que queremos y el tablespace donde queremos ubicar la tabla.

CREATE TABLE usuario_prueba.nombre_tabla
 TABLESPACE tablespace
 PCTUSED    40
 PCTFREE    10
 INITRANS   1
 MAXTRANS   255
 STORAGE    (
 INITIAL          10016K
 NEXT             10000K
 MINEXTENTS       1
 MAXEXTENTS       499
 PCTINCREASE      0
 FREELISTS        1
 FREELIST GROUPS  1
 BUFFER_POOL      DEFAULT
 )
 LOGGING
 NOCACHE
 NOPARALLEL AS SELECT * FROM USUARIO_PRUEBA.TABLA@MY_DBLINK;

En este otro ejemplo, el storage que tendrá la tabla será el especificado en la misma sentecia CREATE TABLE, y los datos los cogerá exactamente igual que la sentencia anterior.

Convertir campo tipo LONG a VARCHAR2 para compatibilizar con Oracle 7

 

 

 

Os pongo en contexto …

Resulta que necesito saber que vistas de un usuario determinado están usando un DBLINK hacia otra Base de datos y el DBLINK está almacenado en una Base de datos Oracle 7.

Para saber las vistas necesito consultar la vista all_views cuyo campo text me indica el nombre y contenido del DBLINK. Por tanto, necesito realizar una consulta de esa vista y campo y buscar el texto “@nombre_DBLINK”.

¿ Que sucede ?

Basicamente que el campo text de la vista all_views es de tipo LONG y por tanto, el realizar una búsqueda de una cadena determinada dentro de ese campo, usando por ejemplo “like” no funciona, nos dará el error “ORA-00932: tipos de dato inconsistentes. Pues para que funcionase debería ser de tipo CHAR o VARCHAR2.

Ejemplo:

select * from all_views
where text like ‘%@NOMBRE_DBLINK%’;
ORA-00932: tipos de dato inconsistentes

La solución pasa por convertir el campo text de tipo LONG a VARCHAR2 para poder consultar usando like (patrón de búsqueda).

Para este proceso, crearé una tabla llamada tabla_vistas con los campos que necesito consultar y con un campo tipo VARCHAR2 que será el que usaré para almacenar la información del campo text de la vista all_views y que es de tipo LONG.

CREATE TABLE tabla_vistas (
    propietario VARCHAR2(30),
    nombre_vista VARCHAR2(30),
    texto VARCHAR2(2000) -- En este campo almacenaré la información del campo text de all_views
    );

Una vez creada la tabla, cuyos tipos de datos en los campos coinciden con los que necesito de all_views excepto el campo “texto” que contendrá los datos sacados del campo “text” de tipo LONG, crearé un cursor de tipo explícito (que son los que usamos cuando una consulta devuelve más de una fila) que recorra la vista all_views y extraiga la información fila a fila y a su vez almacene cada fila en la nueva tabla creada, pero convirtiendo el campo text de all_views de LONG a VARCHAR2 para posteriormente, yo poder realizar una consulta sobre la tabla resultado usando la opción “like” para buscar una cadena determinada.

Esto se hace de la siguiente manera:

set serveroutput on size 320000
DECLARE
          CURSOR c1 IS
          SELECT owner,view_name, text FROM all_views;
          c_owner VARCHAR2(30);
          c_view_name VARCHAR2(30);
          c_text LONG;
          cadena2000 varchar2(2000);
    BEGIN
       OPEN c1;
      LOOP
          FETCH c1 INTO c_owner,c_view_name,c_text;
          cadena2000 := substr(c_text,1,2000);
          INSERT INTO tabla_vistas (propietario,nombre_vista,texto) VALUES (c_owner,c_view_name,cadena2000);
          EXIT WHEN c1%NOTFOUND;
           DBMS_OUTPUT.PUT_LINE('No se han encontrado datos.');
       ENDLOOP;
       CLOSE c1;
    END;

Ahora ya podemos realizar la consulta sobre la tabla “tabla_vistas” que contendrá todas las filas de all_views con los campos que necesitábamos y con el campo “text” de tipo LONG convertido a tipo VARCHAR2 en el campo “texto” del ejemplo.

select * from tabla_vistas

where texto like '%@NOMBRE_DBLINK%'; -- Texto a buscar en la tabla resultados