Saltar al contenido

www. La Mandarina Mecánica .es

…ahora con internet los niños se te educan solos… Homer Simpson…

Archivo

Categoría: ORACLE

Este error de Oracle, traducido sería algo así:

TNS:el listener no ha encontrado ningún manejador disponible con una pila de protocolos coincidente

El otro día nos dió aquí al tratar de conectar a BBDD, y era porque estabamos cerca de alcanzar el número máximo de sesiones y procesos establecidos.

Si en máquina ejecutais cualquiera de estas dos líneas, os dará el número de conexiones que hay en ese momento:

ps -ef | grep oracleSID | grep -v grep | wc -l
ps aux | grep oracleSID | grep -v grep | wc -l

Teneís que poner oracle unido al SID de vuestra BBDD.

Luego os conectáis a BBDD para comprobar si estáis cerca del valor máximo de procesos y sesiones establecido:

select NAME, DISPLAY_VALUE, DESCRIPTION from v$parameter where name in (’processes’,’sessions’);

Si es así, lo podéis aumentar de esta manera:

SQL> alter system set processes=300 scope=spfile;
SQL> alter system set sessions=300 scope=spfile;

Luego sólo queda tirar y levantar la BBDD (siempre que tengamos los permisos suficientes)

SQL> shutdown immediate;
SQL> startup;

Claro que si no tenéis permisos hacer esto, siempre podéis “eliminar” conexiones. Si no sabéis como, echarle un ojo a otro post que hay por ahí publicado sobre esto. 

Oracle Forms es un software para crear pantallas que interactúan con una base de datos (oracle), éste es un poco limitado, con lo que a veces necesitamos incluir Jbean dentro de nuestras aplicaciones. Para esto basta con hacer un .jar e incluir éste dentro de la pantalla o fmb.
Para integrar un java Bean en Oracle Forms, necesitamos copiar el bean.jar dentro del directorio <ORACLE_HOME>/forms/java
Luego editamos el archivo formsweb.cfg y añadimos el bean.jar.

# Forms applet archive setting for JInitiator
archive_jini=f90all_jinit.jar, archivo.jar
# Forms applet archive setting for Microsoft Internet Explorer native JVM
archive_ie=f90all.cab, archivo.jar

Añadimos el Bean en la pantalla y ponemos la ruta y el nombre del bean.jar en las propiedades del Bean, en Clases de implementación añadimos:
oracle/forms/archivo (sin la extensión).

Primero crearemos el directorio para trabajar. Tenéis que tener permisos para hacerlo:
create or replace directory DIR_TEST as ‘/usuarios/prueba’;
Si queréis borrarlo:
drop directory DIR_TEST;
Con esta select podréis ver todos los directorios creados:
select * from dba_directories;

OPERATIVA
Para trabajar con ficheros, es básico conocer la operativa de las dos operaciones más normalmente usadas.
ESCRITURA
1.     Declarar el descriptor
2.     Abrir el fichero con FOPEN de modo escritura
3.     Escribir los datos usando PUT, FPUT o PUT_LINE.
4.     Cerrar fichero FCLOSE

LECTURA
1.     Declarar el descriptor
2.     Declarar variable para almacenar datos
3.     Abrir el fichero con FOPEN de modo lectura.
4.     Leer datos con GET_LINE
5.     Cerrar fichero FCLOSE

continúe leyendo…

Con este paquete podemos obtener el código DLL (sentencia de creación) de cualquier objeto de BBDD.

 

Con la función GET_DDL de este paquete, extraeremos la DLL. Su sintaxis es la siguiente:

 

DBMS_METADATA.GET_DDL (
object_type IN VARCHAR2,
name IN VARCHAR2,
schema IN VARCHAR2 DEFAULT NULL,
version IN VARCHAR2 DEFAULT ‘COMPATIBLE’,
model IN VARCHAR2 DEFAULT ‘ORACLE’,
transform IN VARCHAR2 DEFAULT ‘DDL’)
RETURN CLOB;
 

 

 

Los parámetros que utiliza son:

1 .Tipo de objeto (tabla, index, vista…)

2. Nombre del objeto

3. El esquema al que pertenece ( No es necesario)

4. Versión de servidor para la cual se extraerá el código. Establece un filtro que limita la extracción del metadata para objetos superiores la versión indicada, que nunca puede ser menos de la 9.2.0.

5. Model: Por ahora sólo ORACLE

6. Con este parámetro podemos indicar si el metadata lo devolverá en DDL o en XML

 

 

 

SELECT dbms_metadata.get_ddl(’TABLE’, ‘PRUEBA’, ‘ORACLE’) from dual;

Devolvería:

  CREATE TABLE “ORACLE”.”PRUEBA”

   (    “NOMBRE” VARCHAR2(1)

   ) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING

  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645

  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)

  TABLESPACE “ORACLE4″

 

continúe leyendo…

Es una nueva funcionalidad, a partir de Oracle 10gR2, que nos permite ejecutar una sentencia DML completa y si en el transcurso de la ejecución, algún registro diera error, se insertará en una tabla de error para, posteriormente, poder corregirlo y volver a insertarlo, continuando con los siguientes registros.

Así no tendremos que ir controlando por registro o por bloque de registros si se ha producido un error para realizar el commit.

 

Lo primero de todo. Ver si lo tenemos instalado:

 SELECT OBJECT_NAME FROM ALL_OBJECTS

      WHERE OBJECT_NAME LIKE ‘%DBMS_%’

          AND OBJECT_TYPE = ‘PACKAGE’ ORDER BY 1;

Si creamos una tabla:

  continúe leyendo…

Antes de esta sentencia, que vino implementada en Oracle 9,  cuando se quería insertar/actualizar datos en una tabla que no estaba vacía, teníamos que ir procesando los registros y comprobar si estaba en la tabla antes de realizar un UPDATE o un INSERT, con algún tipo de lenguaje procesual.

Este tipo de sentencia permite actualizar registros (UPDATE) cuando la condición se cumple o insertar registros (INSERT) cuando la condición no se cumple.  Eso si, no es recomendable en cargas masivas de datos!

Esta sentencia tiene esta sintaxis:

MERGE INTO [tabla_destino]
USING ([tabla o vista o consulta])
ON ([condición de existencia de registro])
WHEN MATCHED THEN [sentencia de actualización]
WHEN NOT MATCHED THEN [sentencia de inserción];

MERGE INTO RESTO res USING prueba_tmp pru

ON (res.ID = pru.ID)

WHEN MATCHED THEN

UPDATE SET

 res.DNI = pru.DNI,

 res.departamento = pru.departamento

WHEN NOT MATCHED THEN

INSERT (ID, DNI, DEPARTAMENTO)

VALUES (pru.ID, pru.DNI, pru.DEPARTAMENTO)

He intentado meter más condiciones en la clausula ON, pero no he podido y tampoco he visto información al respecto.

Esta sentencia tiene otras posibilidades:

-       Sólo  insert (NOT MATCHED):

MERGE INTO RESTO res USING prueba_tmp pru

ON (res.ID = pru.ID)

WHEN NOT MATCHED THEN

INSERT (ID, DNI, DEPARTAMENTO)

VALUES (pru.ID, pru.DNI, pru.DEPARTAMENTO)

-       Sólo update (MATCHED):

MERGE INTO RESTO res USING prueba_tmp pru

ON (res.ID = pru.ID)

WHEN MATCHED THEN

UPDATE SET

 res.DNI = pru.DNI,

 res.departamento = pru.departamento

-       Con condiciones en el INSERT o el UPDATE ( Las condiciones tienen que basarse en la tabla de la que se recoge los datos)

MERGE INTO RESTO RES USING PRUEBA_TMP PRU

ON (RES.ID = PRU.ID)

WHEN MATCHED THEN

UPDATE SET

 RES.DNI = PRU.DNI,

 RES.DEPARTAMENTO = PRU.DEPARTAMENTO

WHERE PRU.DEPARTAMENTO != ‘CONTABILIDAD’

WHEN NOT MATCHED THEN

INSERT (ID, DNI, DEPARTAMENTO)

VALUES (PRU.ID, PRU.DNI, PRU.DEPARTAMENTO)

WHERE PRU.DEPARTAMENTO != ‘Contabilidad’

 

-       Con Delete (Siempre con el UPDATE) Haremos un update y luego borraremos los que pertenezcan a un departamento en la tabla en la que hemos hecho el update:

 

MERGE INTO RESTO RES USING PRUEBA_TMP PRU

ON (RES.ID = PRU.ID)

WHEN MATCHED THEN

UPDATE SET

 RES.DNI = PRU.DNI,

 RES.DEPARTAMENTO = PRU.DEPARTAMENTO

DELETE WHERE PRU.DEPARTAMENTO =  ‘Contabilidad’

 

-       Si queremos utilizarla con parámetros y la tabla DUAL:

 

MERGE INTO RESTO res

USING dual d

ON (res.ID = PARAMETRO1)

WHEN MATCHED THEN UPDATE SET res.DNI = PARAMETRO2

WHEN NOT MATCHED THEN INSERT (res.ID, res.DNI) VALUES (PARAMETRO1, PARAMETRO2);

 

 

Si el MERGE nos devuelve el siguiente error:

 

“ORA-30926: unable to get a stable set of rows in the source tables.

Cause: A stable set of rows could not be got because of large dml activity or a non-deterministic where clause.

Action: Remove any non-deterministic where clauses and reissue the dml.”

 

La verdadera causa del error no está en el “non-deterministic where clause“: quiere decir que hay dos filas de la tabla origen que actualizarían una de la tabla destino.

Desde la versión 9i podemos realizar este tiempo de inserciones. Podemos insertar en más de una tabla de forma paralela, en la misma sentencia, poniendo o no condiciones.

Utilizaremos la tabla EMPLEADOS para verlo más claramente:

 Name                                      Type                       

 DNI                                        VARCHAR2(20)               

 DEPARTAMENTO                VARCHAR2(20)

 EDAD                                    NUMBER(2)

 Crearemos tres tablas con sólo los dos primeros campos para separar a los empleados por edad;

 create table EMPLEADOS_20 as select DNI, DEPARTAMENTO from empleados where 1=0;

create table EMPLEADOS_30 as select DNI, DEPARTAMENTO from empleados where 1=0;

create table EMPLEADOS_40 as select DNI, DEPARTAMENTO from empleados where 1=0;

create table RESTO as select DNI, DEPARTAMENTO from empleados where 1=0;

 Si añadimos la condición WHERE la creará sin datos.

INSERT ALL

Como prueba insertaremos los datos de empleados en todas las tablas:

INSERT ALL

  INTO EMPLEADOS_20

  VALUES (DNI,DEPARTAMENTO)

  INTO EMPLEADOS_30

  VALUES (DNI,DEPARTAMENTO)

  INTO EMPLEADOS_40

  VALUES (DNI,DEPARTAMENTO)

  SELECT DNI,DEPARTAMENTO,EDAD FROM EMPLEADOS;

INSERT ALL WHEN (se insertan los valores especificados en todas las condiciones verdaderas.)

Ahora repartiremos los empleados en las tablas dependiendo de su edad. Crearemos una tabla para recoger al resto de las edades superiores:

 

INSERT ALL

WHEN (EDAD<30) THEN

  INTO EMPLEADOS_20

  VALUES (DNI,DEPARTAMENTO)

WHEN (EDAD<40) THEN

  INTO EMPLEADOS_30

  VALUES (DNI,DEPARTAMENTO)

WHEN (EDAD<50) THEN

  INTO EMPLEADOS_40

  VALUES (DNI,DEPARTAMENTO)

ELSE

      INTO RESTO

  VALUES (DNI,DEPARTAMENTO)

SELECT DNI,DEPARTAMENTO,EDAD FROM EMPLEADOS;

INSERT FIRST WHEN (sólo se insertan los valores especificados en la primera condición verdadera)

Si existe un empleado que tenga más de 50, aunque cumple la condición para ir a la tabla de EMPLEADOS_40 también,  se insertará en la tabla RESTO solamente, porque es la primera condición verdadera. 

 

INSERT FIRST

  WHEN (EDAD>50) THEN

    INTO RESTO

    VALUES (DNI,DEPARTAMENTO)

  WHEN (EDAD<30) THEN

    INTO EMPLEADOS_20

    VALUES (DNI,DEPARTAMENTO)

  WHEN (EDAD<40) THEN

    INTO EMPLEADOS_30

    VALUES (DNI,DEPARTAMENTO)

  WHEN (EDAD>40) THEN

    INTO EMPLEADOS_40

    VALUES (DNI,DEPARTAMENTO)

  SELECT DNI,DEPARTAMENTO,EDAD FROM EMPLEADOS 

Limitaciones:

La suma del total de las columnas INTO no puede exceder 999

Sólo funciona en tablas, no en vistas o vistas materializadas.

Para probar esto, realizaremos un insert en una tabla y no realizaremos el commit, al intentar borrarla desde otra sesión nos devolverá  un error tipo:

ORA-00054: resource busy and acquire with NOWAIT specified

Esta select nos devolverá las tablas que están bloqueadas. 

SELECT

decode(L.TYPE,’TM’,'TABLE’,'TX’,'Record(s)’) TYPE_LOCK,

decode(L.REQUEST,0,’NO’,'YES’) WAIT,

S.OSUSER OSUSER_LOCKER,

S.PROCESS PROCESS_LOCKER,

S.USERNAME DBUSER_LOCKER,

O.OBJECT_NAME OBJECT_NAME,

O.OBJECT_TYPE OBJECT_TYPE,

concat(’ ‘,s.PROGRAM) PROGRAM,

O.OWNER OWNER,

s.SID,

s.serial#

FROM v$lock l,dba_objects o,v$session s

WHERE l.ID1 = o.OBJECT_ID

AND s.SID =l.SID

           AND l.TYPE in (’TM’,'TX’)

Lo desbloquearemos de las siguientes maneras, con el SID y SERIAL# que hemos recuperado anteriormente: 

1. ALTER SYSTEM DISCONNECT SESSION ‘SID, SERIAL#’ IMMEDIATE;
2. ALTER SYSTEM KILL SESSION ‘SID, SERIAL#’ IMMEDIATE;

En el caso de que no finalice el proceso podemos matarlo desde el SO:  

3. kill -9 SPID. Donde el SPID lo podemos obtener en esta consulta:  

select substr(a.os_user_name,1,8) “OS User”

, substr(b.object_name,1,30) “Object Name”

, substr(b.object_type,1,8) “Type”

, substr(c.segment_name,1,10) “RBS”

, e.process “PROCESS”

, substr(d.used_urec,1,8) “# of Records”

, e.sid

, e.serial#

, p.*

from v$locked_object a

, dba_objects b

, dba_rollback_segs c

, v$transaction d

, v$session e

, v$process p

where a.object_id = b.object_id

and a.xidusn = c.segment_id

and a.xidusn = d.xidusn

and a.xidslot = d.xidslot

and d.addr = e.taddr

and p.addr = e.paddr

and substr(b.object_name,1,30)=NOMBRE_TABLA

Vamos a generar cadenas XML a partir de registros de una select.

XMLElement sirve para generar un elemento XML por cada registro recuperado.

 

select xmlElement(”Título”, post_title) from menu;

 

<Título>Resumen Java - Modificadores de Acceso.</Título>

<Título>Resumen Java - Tipos de Variables.</Título>

<Título>Super Bluetooth Hack</Título>

<Título>Password - Ubuntu </Título>

<Título>Ubuntu - Beryl</Título>

<Título>Clase System</Título>

<Título>ACCEDER AL IPOD TOUCH MEDIANTE FTP</Título>

<Título>Java</Título>

<Título>Ubuntu</Título>

<Título>Iphone</Título>

 

 

Si queremos poner atributos a los elementos  utilizaremos XMLAttributes:

 

select xmlElement(”Título”, XMLAttributes(idmenu as NIVEL),

       xmlElement(”Nombre”, post_title)) from menu

       order by idMenu

 

 

<Título NIVEL=”1″><Nombre>Java</Nombre></Título>

<Título NIVEL=”2″><Nombre>Ubuntu</Nombre></Título>

<Título NIVEL=”3″><Nombre>Iphone</Nombre></Título>

<Título NIVEL=”4″><Nombre>Resumen Java - Modificadores de Acceso.</Nombre></Título>

<Título NIVEL=”5″><Nombre>Resumen Java - Tipos de Variables.</Nombre></Título>

<Título NIVEL=”6″><Nombre>Super Bluetooth Hack</Nombre></Título>

<Título NIVEL=”7″><Nombre>Password - Ubuntu </Nombre></Título>

<Título NIVEL=”8″><Nombre>Ubuntu - Beryl</Nombre></Título>

<Título NIVEL=”9″><Nombre>Clase System</Nombre></Título>

<Título NIVEL=”10″><Nombre>ACCEDER AL IPOD TOUCH MEDIANTE FTP</Nombre></Título>

 

Si uno de los registros tiene un valor nulo, nos lo devolverá vacío de esta manera:

 

<Título NIVEL=”1″><Nombre></Nombre></Título>

 

Para evitarlo utilizaremos XMLForest, permite realizar consultas de forma más compacta y omite los que son nulos pero no admite la utilización de atributos.

 

select xmlElement(”Título”, XMLAttributes(idmenu as NIVEL),

       xmlForest(post_title as “Name”,

       url as “URL”)) from menu

       order by idMenu

 

XMLAGG es una función de agregación. A partir de una colección de fragmentos XML, devuelve un único documento agregado.

Devolveremos en cada elemento TITULO todos los nombres que pertenezcan al mismo idRelacion.

  

select xmlElement(”Título”, 

       xmlAgg(xmlElement(”Name” ,post_title,

       “URL” ,url)) )

       from menu

       group by idRelacion

 

<Título><Name>Resumen Java - Modificadores de Acceso.</Name><Name>Clase System</Name></Título>

<Título><Name>Password - Ubuntu </Name><Name>Ubuntu - Beryl</Name></Título>

<Título><Name>Super Bluetooth Hack</Name><Name>ACCEDER AL IPOD TOUCH MEDIANTE FTP</Name></Título>

<Título><Name>Resumen Java - Tipos de Variables.</Name></Título>

<Título><Name>Java</Name><Name>Iphone</Name><Name>Ubuntu</Name></Título>

 

Podéis encontrar mucha más información en:

 

http://download-uk.oracle.com/docs/cd/B19306_01/server.102/b14200/toc.htm

Navigation »