Mostrando las entradas con la etiqueta Oracle. Mostrar todas las entradas
Mostrando las entradas con la etiqueta Oracle. Mostrar todas las entradas

domingo, 29 de mayo de 2011

SqlDeveloper Timezone region not found

El error "ORA-01882: timezone region not found" es uno que ya me había ocurrido en el Sql Developer con anterioridad al ejecutar consultas a través de db links. En algunos foros mencionan que este es un error que ocurre al consultar un servidor Oracle 10g desde un cliente 9i, aunque actualmente tengo cliente 10g hacia un servidor 10g también y el error me sigue apareciendo lo cual me estaba impidiendo conectarme al servidor.

Me da la impresión que sucede al utilizar software que utilice el JDK ya que con aplicaciones en .NET no me ha sucedido.


El mensaje de error es el que aparece en la imagen anterior y su solución es bastante sencilla. Basta con buscar el archivo sqldeveloper.conf y añadir la siguiente línea al mismo:

AddVMOption -Duser.timezone="-8:00"

Mediante esa línea se le indica al Sql Developer que establezca la zona horaria del usuario a -8:00, ese número debería ser sustituido por tu zona horaria. Con eso ya queda solucionado el problema al intentar conectarse y probablemente también el que ocurría al momento de realizar consultas a través de Db Links.

Si el error te está ocurriendo al realizar una consulta y no precisamente al conectarse, puedes utilizar el siguiente query para cambiar el valor de la zona horaria durante la sesion:

alter session set time_zone = '-8:00'

Eso es todo por este post, espero que les sea de ayuda.

viernes, 9 de octubre de 2009

Oracle UPSERT

En ocasiones resulta que necesitamos insertar un dato en la tabla si es que no existe ó actualizar (hacer un update) si es que sí existe. La primera solución que se viene a la mente tal vez sea la de:

select count(*) into CNT from where

if CNT = 0 then
insert into ...
else
update ....
end if;

Sin embargo existe otra manera más elegante de hacerlo que nos evita realizar el select-count inicial y se refiere a utilizar el valor de la pseudo-variable SQL%NOTFOUND que es un indicador que nos dice si la última instrucción de Update tuvo o no éxito (si encontró o no registros a modificar).

Utilizando esa propuesta, nuestro código quedaría de esta forma:

UPDATE set = where

if SQL%NOTFOUND then
insert into ...
end if;

Creo que de la forma anterior (sql%notfound) obtenemos un código más limpio y que en caso de tener un update exitoso nos ahorramos también tiempo de ejecución al no tener que hacer un conteo inicial.

Existe también otra posible solución que es la de utilizar la sentencia MERGE pero hablaremos de ella en otro post en un par de días.

sábado, 30 de mayo de 2009

Leer un Oracle REF CURSOR en ASP.NET

En ocasiones me ha resultado más conveniente que la aplicación web obtenga los datos consultando un procedimiento almacenado que devuelve un Ref Cursor en Oracle. Lo anterior debido a que en caso de ser necesario realizar algún cambio en la consulta, por ejemplo cambiar algunas condiciones en el select ó realizar alguna corrección.

De esta manera nos evitamos tener que modificar el código fuente y tener que dejarlo nuevamente en el servidor web. Además, podemos tomar el código del procedimiento almacenado y ejecutarlo en nuestras herramientas de desarrollo, SqlDeveloper en mi caso, para verificar resultados sin tener que pasar por todas las páginas involucradas en la aplicación web.

Recientemente me enfrenté al problema de que en ASP.NET surgían errores al tratar de obtener los valores desde un Ref Cursor.

Para el ejemplo, tenemos declarado el siguiente procedimiento Oracle:

PROCEDURE GET_TEST(cData OUT CursorType, XTRA OUT VARCHAR2)
IS
BEGIN
xtra := 'AE';

OPEN
cDATA FOR
SELECT
*
FROM DUAL;
END;



A continuación el código en ASP.NET (recortado, claro)

Dim DbCn as OracleConnection

' Codigo de asignación de propiedades para la conexion

' Codigo de apertura de conexion
DbCn.Open
Dim Cmd As OracleCommand = DbCn.CreateCommand
Cmd.CommandText
= "GET_TEST" ' Nombre del procedimiento almacenado
Cmd.CommandType = Data.CommandType.StoredProcedure

' Adición de los parámetros, en este caso uno de tipo RefCursor y el otro de tipo Varchar2
Cmd.Parameters.Add("pRET", OracleDbType.RefCursor).Direction = Data.ParameterDirection.Output
Cmd.Parameters.Add(
"PX", OracleDbType.Varchar2).Direction = Data.ParameterDirection.Output
Cmd.Parameters(
"PX").Size = 20

Cmd.ExecuteNonQuery()

' Obtención de los valores devueltos
Dim XX As String = Cmd.Parameters("PX").Value.ToString
Dim RC As Oracle.DataAccess.Types.OracleRefCursor = Cmd.Parameters("pRET").Value
Dim Da As New OracleDataAdapter
Dim dt As New System.Data.DataTable
Da.Fill(dt, RC)

' Eliminamos los objetos
RC.Dispose()
Da.Dispose()
DbCn.Close()

Me.GridView1.DataSource = dt
Me.GridView1.DataBind()


Quedan por hacer algunos comentarios:
  • Para algunos tipos de parámetro es necesario indicar la longitud del dato, tal es el caso de los Varchar2, en este caso, si al parámetro no se le indica un Size (20 en el ejemplo) entonces ocurrirá un error que indicará que la variable no es lo suficientemente grande como para almacenar el valor retornado.
  • Al objeto OracleCommand es necesario indicarle que el tipo de comando es "StoredProcedure" y entonces en el CommandText pondremos el nombre del procedimiento SIN parámetros ya que los parámetros los añadiremos después.
  • Los parámetros deberán ser añadidos en el orden en que aparecen en la declaración del stored procedure.
  • Luego de ejecutar el objeto comando con ExecuteNonQuery, obtendremos el valor del parámetro correspondiente a un OracleRefCursor y lo asignaremos a una variable de ese tipo, todo esto para después llenar un DataTable (ó DataSet) a través de un OracleDataAdapter ya que éste puede llenar la DataTable a través del objeto OracleRefCursor.
  • Luego de lo anterior ya podremos utilizar nuestro DataTable puesto que ya contendrá la información cargada.
  • Es posible leer de procedimientos que retornen más de un OracleRefCursor.
Espero que el presente post les haya sido de utilidad. Cualquier comentario, sugerencia o duda allí tienen el espacio de comentarios para expresarse =)