Archive for the ‘oracle’ Category

ORA-00604 se ha producido un error a nivel 1 de SQL recursivo. ORA-01655 con GeneXus y Oracle

Tuesday, August 28th, 2007


ORA-00604: se ha producido un error a nivel 1 de SQL recursivo.
ORA-01655: no se ha podido ampliar el cluster SYS.c_FILE#_BLOCK# con 8 en el tablespace SYSTEM

Testeando una aplicación con .NET y Oracle 10g Express Edition al crear la base de datos con GeneXus, la misma falló indicando el error mencionado.

La versión de Oracle 10g Express es limitada en algunos aspectos.
Por default en su instalación define un tablespace system, undo, otro de usuarios y no posee una administración gráfica de estos objetos.
Es decir no existe posibilidad de manipular, alterar tamaño etc, de estos objetos de forma gráfica y hay que ejecutar comandos en línea.

El error se debía a que el tablespace de system es definido por default con 600 mb y (por apresurado) al crear el usuario/esquema con el cual corrí la creación de las tablas no lo asocié con otro tablespace que no sea system, por ejemplo “users” y llené el datafile de system.

La solución sería borrar el usuario creado con opción cascada y así borraría todas las tablas creadas hasta el momento y crear nuevamente el usuario asociándolo al tablespace correcto.

La otra alternativa, más rápida, sería agrandar el tablespace system con el siguiente comando de línea.

ALTER DATABASE DATAFILE ‘D:\ORACLEXE\ORADATA\XE\SYSTEM.DBF’ RESIZE 1000M;

Pero como comenté antes es lo menos recomendable, pero también funciona si es algo rápido y no definitivo que estamos probando simplemente.

Si te interesa saber, las limitantes para usar Oracle 10g Express Edition son:

1 GB de memoria para el servidor de base de datos
1 procesador
Una instancia por equipo
Espacio disponible para datos e índices 4GB.

Fabricio De los Santos
Gerencia de Proyectos -
Consultoría GeneXus -
ERP – Sistemas de Misión Crítica - Bases de Datos.

Vea mis blogs en:
www.fabriciodelossantos.com

ORA-03113 end of file on communication file en Oracle con comando Analyze

Monday, August 13th, 2007

El otro día comentaba un error de Oracle ORA-03113 el cual sinceramente, es uno de los más desagradables que puede dar Oracle, porque ciertamente, antes de ocurrir este error ocurrió otro previo.
En el post anterior refería a un renombrado de tablas y pérdida de estadísticas.
Bien, la solución era Analizar las tablas involucradas nuevamente.
Como prevención comenzamos a utilizar esta estrategia, pero nos encontramos con el mismo error, pero ahora desde el Sqlplus.
El problema era que algunas de las tablas que queríamos Analizar, tenían dentro de las columnas claves, “caracteres extraños” del tipo chr(10) chr(13), etc.
Para descubrir esto simplemente bastó hacer un group by por cada campo de la tabla y en algunos casos ya obtuvimos el ORA-03113

Ejemplo:

Tabla1
Col1 char(30)
Col2 char(30)
Col3 char(30)

Col1
A
A
B

Col2
A||B
A||C
AB

(Los || simulan los caracteres especiales que no los puedo reproducir en el post)

Col3
A
B
C

Al realizar un select Col1,count(*) from Tabla1 group by Col1;
El resultado es correcto

Idem para Col3

Pero al realizar la consulta para Col2, luego de no demorar mucho, obtenemos el ORA-03113

Por fortuna, estábamos a punto de instalar el patch 4547809 para Oracle 9.2.0.8 lo cual fue realizado, y para nuestra sorpresa… los analize comenzaron a funcionar perfectamente.

Entonces recomiendo actualizar este patch para quienes no lo hayan hecho y estén con Oracle 9 ya que además de este, soluciona un paquete grande de bugs.

Fabricio De los Santos
Gerencia de Proyectos -
Consultoría GeneXus -
ERP – Sistemas de Misión Crítica - Bases de Datos.

Vea mis blogs en:
www.fabriciodelossantos.com

ORA-03113 end of file on communication file con GeneXus y Oracle

Friday, August 10th, 2007

En algunos casos tenemos algunos reportes pdf o excel que van sobre un DataView GeneXus que apunta a Views complejas en Oracle, para ganar performance.
Hace algunos días renombramos algunas tablas que participan en algunas de esas views y nos encontramos con un error ORA-03113 ejecutando la aplicación.
Lo interesante es que pasaba en un servidor y en otro no.
La diferencia estaba en la capacidad de uno y otro, procesador, memoria, etc, en el que no daba problema, eran mayores que en el servidor que retornaba el error.
Luego de buscar que había cambiado de una fecha para acá, encontramos que podría ser el “renombrado de tablas” la causa del problema.
Solución corrimos las estadísticas nuevamente para las tablas renombradas y todo volvió a la normalidad.

Ejemplo:

analyze table nuestratabla compute statistics;

Existen distintas variantes del comando analyze pero con la más simple de todas, ya soluciona el problema.

Fabricio De los Santos
Gerencia de Proyectos -
Consultoría GeneXus -
ERP – Sistemas de Misión Crítica - Bases de Datos.

Vea mis blogs en:
www.fabriciodelossantos.com

Como simular una función Session o Variable Global en Win con GeneXus y Oracle

Tuesday, July 3rd, 2007

Cuando trabajamos en Web y queremos distinguir una sesión de otra podemos utilizar una variable de tipo WebSession.
Esto básicamente queda muy claro en cualquier ejemplo GeneXus generado por patterns, etc.

Un ejemplo puede ser el procedimiento SetContext de GxWiki

&Session.Set(WikiParameters.Context, &Context.ToXml())

Básicamente seteamos en la variable de tipo WebSession algo particular, en este caso un SDT que se llama context.

Ahora bien, por que querría o precisaría tener algo similar a una WebSession pero en una aplicación Windows?

Si bien desde siempre existen las funciones UserID() y Wrkst() que podrían darme esa unicidad que preciso, dependiendo de la aplicación o de algunas limitantes o que nos encontremos, cantidad de licencias, etc, puede ser que ni la combinación de estas 2 funciones mencionadas, nos pueda garantir el dato de una sesión dentro de mi aplicación.

Por ejemplo:

Tengo una aplicación corriendo bajo Terminal Services con licencia para 10 usuarios, donde el nombre de usuario podría no indicarme nada en particular, digamos podrían ser del tipo User1, User2, etc, para lo cual si usara la función UserID() para grabar una auditoría en un registro, no me serviría de mucho.

New
xxxx=yyyy
xxxx=yyyy
xxxx=UserID()
EndNew

Entonces podría llegar a otra solución

Aplico un login y password en una pantalla cuando ingreso al sistema y lo asocio con UserID()
Algo sencillo para ejemplificar (sin contemplar cientos de criterios de seguridad) sería más o menos así:

For Each //Usuarios
Where UsrCod=&UsrCod
Where UsrPsw=&UsrPsw
New //Log
LogUsrID=UserID()
LogUsrCod=UsrCod
EndNew
EndFor

Para luego volver a mi rutina de auditoria

New
xxxx=yyyy
xxxx=yyyy
xxxx=udp(pUserID)
EndNew

Donde “pUserID” seria una recorrida de la tabla Log usando como condición “LogUsrID=UserID()” y devolviendo como resultado el valor de “LogUsrCod” que podria ser “Juan”

Perfecto, ahora si tengo un Usuario que conozco registrado para auditoría.

Pero bien, complicándola un poco más, que pasaría si ese “User1″ (del Terminal) está ejecutando mi aplicación y necesita ejecutar otra instancia?

No habría problemas, porque si bien no podría hacer el “New” en la tabla de “Log”, con la función “UserID()” obtendría el mismo dato, o sea “Juan”

Pero…

Si este mismo “User1″ (del Terminal) en vez de entrar como “Juan”, necesita entrar como “Pedro”?
No podré hacer un “New”, y ni pensar de utilizar un “When Duplicate” porque reemplazaría un usuario por otro para dos sesiones distintas!

Mmm…
Esto me hace pensar que a partir de la primera pantalla, tendré que pasar por parámetro el usuario que se logueó. Es una solución un poco tediosa, porque objetos que no contemplé antes voy a tener que acomodar para recibir este parámetro.

Sería una solución contar con una función WinSession() que me devuelva la sessión del usuario que está conectado a la base de datos. Claro, su funcionamiento interno sería particular para cada DBMS. Pero, por mientras esto no esté en GeneXus, podemos simularlo mezclando algunos ingredientes de Oracle y luego cada uno puede aplicarlo en su DBMS de desarrollo.

1) Debemos crear una view en nuestra base de datos.

CREATE OR REPLACE FORCE VIEW MISESSION AS
select userenv(’SESSIONID’) SESSIONID from dual;

2) En GeneXus, creamos un DataView a esa View de Oracle con un atributo para identificar la sesión.

3) Luego creamos un procedimiento que nos devuelva la sesión, para esto, hacemos un simple for each que recorra este data view, el cual para nuestra sesión solo va a devolver un registro.
En mi ejemplo lo llame “pmisession”

&MiSession=0
For Each //MISESISON
Defined By SessionID
&MiSession=SessionID
EndFor

Y listo, ahora simplemente en vez de utilizar la función UserId() o Wrkst(), llamaré a este procedimiento para obtener mi variable única.

Y si eres demasiado cómodo (y sólo si estás acostumbrado con el underground de GeneXus), puedes adicionar esta “función personalizada” a los archivos “*func.pst” en el directorio de GeneXus con la sintaxis

pmiession.Udp():Numeric

para que de esta forma cuando la quieras utilizar, simplemente presionando “Ctrl + U”, aparezca dentro de la lista de funciones.

Otras de las posibilidades sería usar el comando SQL de GeneXus, pero lamentablemente, no permite devolver resultados, si existiera una variante del mismo que permitiera en algunos casos devolver un resultado único para almacenar en una variable GeneXus, podría ser algo parecido a esto:

&sent=”select userenv(’SESSIONID’) from dual;”
&misession= sql [!&sent!]

Pero… por ahora no existe.

Observación:
Puede parecer simple o de poco valor esta función de unicidad, pero realmente es algo útil.
Hace unos años en otra empresa, implementamos un sistema con una KB que usaba la función Wrkst() (y todavía lo sigue usando) para mantener la unicidad, y para que cada máquina corra en una sessión única, deshabilitamos la posibilidad que se ejecutara el sistema más de una vez por máquina, justamente para tener esa unicidad, algo que hoy realmente se podría solucionar de esta forma, que ya existía en aquella época, pero a veces uno toma las cosas como vienen y basados en el lema “lo que funciona no se cambia”, a veces perdemos eficiencia.

Fabricio De los Santos
Gerencia de Proyectos -
Consultoría GeneXus -
ERP – Sistemas de Misión Crítica - Bases de Datos.

Vea mis blogs en:
www.fabriciodelossantos.com

Insert Update de Caracteres especiales en Oracle ‘ chr(39)

Tuesday, June 26th, 2007

Insert Update de Caracteres especiales en oracle ‘ chr(39)

Acostumbrado a trabajar con GeneXus, cuando necesito insertar o actualizar un valor con comilla simple en una columna caracter, la operación es muy sencilla:

atributo=”‘hola mundo’”

Ahora cuando queremos hacer esto en un script, usando por ejemplo sqlplus, la operación es distinta.

Básicamente hay que colocar otra comilla simple antes de la que queremos poner, de la siguiente forma:

insert into fdtest values(”’hola mundo”’);

Ahora bien si el caso que tenemos es al revés.

Tenemos en la tabla comilla simple y queremos pasarlas a dobles, nos encontramos, con el mismo problema, porque en la función replace no podemos invertir las comillas para hacer la búsqueda.

La solución en este caso es:

En el parámetro de búsqueda, usar el valor ascii de este caracter especial de la siguiente forma

select replace(campo,chr(39),’”‘) from fdtest;

Nuestro resultado será:

“hola mundo”

Fabricio De los Santos
Gerencia de Proyectos -
Consultoría GeneXus -
ERP – Sistemas de Misión Crítica - Bases de Datos.

Vea mis blogs en:
www.fabriciodelossantos.com

Diferencia entre Unique y Primary Key Oracle ORA-00001: unique constraint violated

Friday, May 25th, 2007

Diferencia entre Unique y Primary Key en Oracle
ORA-00001: unique constraint violated

Cuando escribía este post, me causó curiosidad de porque este es el error número de 1 de Oracle.
Si bien parece algo bastante fácil de explicar, que es lo que está pasando, les cuento que hace unos días me enfrenté con uno de estos, que me quitó bastante tiempo y creo que es bueno compartirlo.

Resulta que un amigo me pidió ayuda con un problema de unique constraint violated y ahi fui a intentar ayudarlo, con grandes posibilidades de resolverlo inmediatamente, pero… la cosa duró un poco más de lo esperado.

Antes de comenzar quiero explicar un poco la diferencia entre una clave de tipo primary key y una de unique.

La diferencia esta en que una clave unique permite nulos, en cuanto una primary key no permite nulos es decir ya incluye la constraint de not null para cada atributo.

Un ejemplo:

Con Primary key

create table fdls01
(col_a number primary key,
col_b number);

insert into fdls01 values(1,1);
1 linha criada.

insert into fdls01 values(null,2);
ORA-01400: cannot insert NULL into (”esquema1″.”FDLS01″.”COL_A”)

Con Unique

create table fdls02
(col_a number unique,
col_b number);

insert into fdls02 values(1,1);
1 linha criada.

insert into fdls02 values(null,2);
1 linha criada.

Como se puede apreciar, en esta segunda ocasión nos dejó hacer el insert sin problema.

Ahora quiero saber que mensaje me da para las 2 tablas, inentando insertar registros ya existentes:

luego probamos las constraints
insert into fdls01 values(1,1);
ORA-00001: unique constraint (esquema1.SYS_C0032094) violated

insert into fdls02 values(1,1);
ORA-00001: unique constraint (esquema1.SYS_C0032095) violated

Las 2 dan el mismo error

Ahora tomando el nombre de la constraint violada, buscaremos en la vista de constraints, cual es la diferencia entre ellas:

si buscamos la constraint en la vista de constraints

select owner,constraint_name,constraint_type from user_constraints
where constraint_name like ‘%SYS_C0032094%’;

OWNER CONSTRAINT_NAME C
—————————— —————————— -
esquema1 SYS_C0032094 P

select owner,constraint_name,constraint_type from user_constraints
where constraint_name like ‘%SYS_C0032095%’;

OWNER CONSTRAINT_NAME C
—————————— —————————— -
esquema1 SYS_C0032095 U

la diferencia esta en el type

Bien ahora yendo al problema presentado por mi amigo

El problema radicaba en que alguien habia creado una tabla sin usar unique como constraint pero usando indices unique para reflejar lo mismo. Algo que no aconsejo, pero paso a explicar en detalle:

create table fdls03
(col_a number,
col_b number);

notar que no esta la cláusula unique como lo había hecho en los ejemplos anteriores.

y luego creo el indice

create unique index fdls03_pk on fdls03(col_a);

e intento hacer los 2 inserts como lo hice en el ejemplo anterior

insert into fdls03 values(1,1);
1 linha criada.

insert into fdls03 values(null,2);
1 linha criada.

permite hacer el insert porque el nulo vale, y al tratar de insertar otro registro repetido

insert into fdls03 values(1,1);
ORA-00001: unique constraint (esquema1.FDLS03_PK) violated

entonces en mi caso particular me encuentro con un nombre FDLS03_PK
que me confundio totalmente con una pk y entonces fui a buscar a la vista de constraints a ver cual era esa constraint

select owner,constraint_name,constraint_type from user_constraints
where constraint_name like ‘%FDLS03_PK%’;

y opa

não há linhas selecionadas

no existe esa constraint! porque alguien en vez de definirla como constraint
simplemente definio la tabla simple sin constraints y uso un indice unique para controlar esto.

El resultado final se podria decir que es el mismo pero… como complicó la vida.
Ademas tenemos que tener en cuenta que en los casos anteriores un indice puede ser dropeado y la tabla sigue funcionando integramente, si dropeamos este ultimo indice la integridad no sera la misma.

Fabricio De los Santos
Gerencia de Proyectos -
Consultoría GeneXus -
ERP – Sistemas de Misión Crítica - Bases de Datos.

Vea mis blogs en:
www.fabriciodelossantos.com

Tips: Error ORA-01536 space quota exceeded for tablespace GeneXus Oracle 9

Friday, May 11th, 2007

Generalmente en modelos de prototipo, el Analista GeneXus acostumbra dar permiso de DBA al usuario, esquema con que está creando las tablas.

El problema es que al entrar en producción, el dba (real) no los va a dejar probablemente con ese permiso, y ahí es donde a veces comienzan los problemas.

Por ejemplo este error reportado puede producirse usando o no GeneXus.

Error ORA-01536 space quota exceeded for tablespace

Lo primero que uno piensa es que no tenemos espacio en el tablespace, (que también podría ser la causa), pero en realidad es falta de “recursos” ya que nuestro usuario no es más DBA.

En este caso podemos sugerir 3 cosas para ese “amigo” DBA

1 - Dar permisos ilimitados de tablespaces a nuestro usuario.
Lo cual dejará los pelos de punta a nuestro DBA

GRANT UNLIMITED TABLESPACE TO “NUESTRO_USUARIO”

2 - Dar una cuota ilimitada para el tablespace que usa nuestro usuario.
Lo cual limita a nuestro usuario con un máximo que depende del tamaño definido para el tablespace.

ALTER USER “NUESTRO_USUARIO” QUOTA UNLIMITED ON “TABLESPACE_QUE_USA”

3 - Dar una cuota real hasta donde su usuario podrá usar, tanto para crear tablas o insertar registros en las tablas

ALTER USER “NUESTRO_USUARIO” QUOTA 100 M ON “TABLESPACE_QUE_USA”;

Obviamente antes de todo esto “NUESTRO_USUARIO” debería haber sido creado, y con ciertos permisos y recursos, (supongo esto ya que sino el error no sería el que estoy mencionando en el post). De todas formas anexo las sentencias asignar estos recursos.

GRANT “CONNECT” TO “NUESTRO_USUARIO”;
GRANT “RESOURCE” TO “NUESTRO_USUARIO”;
ALTER USER “NUESTRO_USUARIO” DEFAULT ROLE ALL

Aprovecho a anexar como auto extender el datafile para que crezca hasta que tengamos disco.

ALTER DATABASE
DATAFILE ‘D:\ORACLE\ORADATA\ORCL\DATAFILE1.ORA’ AUTOEXTEND
ON NEXT 2M

Fabricio De los Santos
Gerencia de Proyectos -
Consultoría GeneXus -
ERP – Sistemas de Misión Crítica - Bases de Datos.

Vea mis blogs en:
www.fabriciodelossantos.com

Tips: Error ORA-12899 insert value too large GeneXus Oracle

Thursday, May 3rd, 2007

Exportamos una base de datos en Oracle 9 y queremos importar los datos en una base de datos Oracle 10

Nos surge el problema que algunos registros de algunas tablas no son importados y nos aparece el mensaje

IMP-00019: Fila rechazada debido al error ORACLE 12899
IMP-00003: se ha encontrado un error 12899 de ORACLE
ORA-12899: el valor es demasiado grande para la columna “Esquema”.”Tabla”.”Columna”

Este problema es porque la base de datos está configurada para multi-byte y caracteres con tilde o algún símbolo puede ocupar dos bytes lo cual hace sobrepasar la capacidad de almacenamiento.

Solución: Borrar el esquema nuevo en la base de datos Oracle 10. Cambiar la variable de ORACLE

NLS_LENGTH_SEMANTICS para CHAR

alter system set NLS_LENGTH_SEMANTICS=CHAR SCOPE=BOTH;

Reiniciar la base de datos, crear nuevamente el esquema, si estás usando GeneXus hacer un CREATE DATABASE, ahora con la variable setadada para char, las nuevas tablas se crearán contemplando esta propiedad.

Luego importa los datos nuevamente, y debería estar solucionado.

Fabricio De los Santos
Gerencia de Proyectos -
Consultoría GeneXus -
ERP – Sistemas de Misión Crítica - Bases de Datos.

Vea mis blogs en:
www.fabriciodelossantos.com

Tips: Error ORA-01407 cannot update to null GeneXus Oracle

Thursday, April 26th, 2007

Este problema básicamente indica que se está intentando hacer un update en una tabla con un valor nulo, cuando el campo no lo permite.

Las opciones son modificar el código del programa o la definción de la transacción GeneXus.
Si el programa puede hacer el update en nulo y la definción en GeneXus es correcta, allownull=yes puede ser que por algun motivo fue cambiado a “mano” en la base de datos las constraints de esa columna.

Para esto último hacer un Describe Nombre_de_Tabla;

Verificar la columna que indica el error si está permitiendo nulos o no.

En el caso que haya sido cambiada a mano, para corregirla, usar la siguiente sentencia SQL

ALTER TABLE Nombre_de_Tabla MODIFY Nombre_de_Columna NULL;

Fabricio De los Santos
Gerencia de Proyectos -
Consultoría GeneXus -
ERP – Sistemas de Misión Crítica - Bases de Datos.

Vea mis blogs en:
www.fabriciodelossantos.com

Tips: Que Version de Oracle estoy ejecutando

Wednesday, April 25th, 2007

Si estamos usando SqlPlus y queremos saber que versión de Oracle es la base de datos a la que estamos conectado, la sentencias para decifrar son las siguientes:

SET SERVEROUTPUT ON SIZE 10000
DECLARE
VERSION1 VARCHAR2(59);
VERSION2 VARCHAR2(59);
BEGIN
dbms_utility.db_version(VERSION1,VERSION2);
DBMS_OUTPUT.PUT_LINE(VERSION1);
DBMS_OUTPUT.PUT_LINE(VERSION2);
END;
/

Version1, nos muestra la versión de la base de datos.
Version2, nos muestra con que versión es compatible la instancia, basado en la configuración setada en el INIT.ORA, si este parámetro de compatibilidad no está seteado, retornará null.

Fabricio De los Santos
Gerencia de Proyectos -
Consultoría GeneXus -
ERP – Sistemas de Misión Crítica - Bases de Datos.

Vea mis blogs en:
www.fabriciodelossantos.com