Informatica Grafica
A P E N D I C E B Oratcl

Oratcl es una extensión de Tcl que proporciona acceso a Oracle, el sistema de gestión de bases de datos relacionales de Oracle, Inc.

Como ya se ha comentado en otra parte de este tutorial, una extensión es un intérprete de Tcl al que se le han incorporado nuevas funciones escritas en C. Estas funciones, una vez compilado el nuevo intérprete, pasan a ser nuevos comandos del intérprete. De esta forma se ha obtenido Tk (cuyo intérprete se denomina wish), al añadir a Tcl funciones que permiten crear entornos gráficos, o Oratcl (cuyo intérprete se suele denominar oratclsh), al añadir a Tcl funciones para el acceso a bases de datos Oracle. Es decir, cualquier programa que funcione con Tcl deberá funcionar igualmente con oratcl, con la única diferencia de que con este último se podrá acceder a bases de datos Oracle.

NOTA: Para todo lo relacionado con la creación de nuevas extensiones en C, consultar el capítulo 23 de este tutorial.


Oratcl

Como ya se ha comentado, Oratcl proporciona el acceso a bases de datos de Oracle. Permite obtener datos de la base de datos servidora, insertar nuevas filas, y actualizar o borrar filas ya existentes. Oratcl permite también el acceso a características avanzadas de Oracle, tales como la lectura o escritura de grandes bloques de datos, y ejecutar procedimientos PL/SQL en la base de datos servidora. Oratcl es compatible con el servidor Oracle versión 6 y versión 7.

Para la compilación de esta extensión son necesarias las librerías OCI de Oracle ("Oracle Call Interface").

Como toda extensión que se precie de serlo, Oratcl añade un numeroso grupo de nuevos comandos al intérprete de Tcl. Todos los comandos que añade irán precedidos por el prefijo "ora" para diferenciarlos de los comandos de uso general de Tcl. Además, Oratcl añade un array de uso global denominado $oramsg, que proporciona información acerca de la ejecución de ciertos comandos de Oratcl.


Comandos básicos

Antes de poder acceder a los datos almacenados en la base de datos, el cliente debe conectarse a la base con un nombre de usuario y un password. Oralogon es el comando que realiza esta conexión.

oralogon cadena_conexion

Oralogon requiere un solo parámetro, la cadena de conexión. Oracle permite que la cadena de conexión sea de cualquiera de estos tipos:

Tabla B-1. Tipos de cadena de conexión.

nombre/password

Nombre de usuario y password.

nombre/password@ servidor

Igual que el anterior pero con el nombre del host local.

nombre/password@ n:host:servidor

Nombre de usuario y password, al que se añade el tipo de conexion n (típicamente T, para TCP/IP), el host, y el nombre del servidor de Oracle.

nombre/password@ alias_servidor

Nombre de usuario y password, al que se añade el nombre del servidor de Oracle, que estará definido en /etc/sqlnet o en un fichero de usuario .sqlnet

Al ejecutarse oralogon, y realizarse la conexión correctamente, devuelve un handle a la conexión abierta en forma de cadena. Este handle es similar al descritor de un fichero al ser abierto con open. Este handle será posteriormente utilizado por otros comandos de Oratcl para operar con la conexión establecida, por lo que será recomendable capturar este handle en una variable Tcl para que pueda ser utilizado como parámetro por otros comandos. Por ejemplo:

set handle [oralogon $cad_conexion]

También es conveniente que la variable que va a almacenar este handle se declare como global, de forma que pueda ser accesible por todos los procedimientos del programa.

En caso de tener varias conexiones a la base de datos, los diferentes handles deberán de ser guardados en diferentes variables Tcl (obvio).

Si la conexión no se ejecuta correctamente debido al uso de un nombre de usuario o password incorrecto, servidor no disponible, etc., oralogon causará un error. La información del motivo por el que no pudo realizarse dicha conexión estará disponible en $oramsg(errortxt).

oraopen handle_conexion

Una vez establecida la conexión se necesita un cursor para poder obtener o insertar datos mediante comandos SQL. Estos cursores (en plural, porque una conexión puede soportar varios cursores) deben de abrirse una vez establecida la conexión, y pueden ser abiertos con el comando oraopen.

set cursor [oraopen $handle]

Los cursores y conexiones de Oratcl deben ser cerrados antes de cerrar la aplicación. Oratcl proporciona comandos para ello.

oraclose cursor_conexion
oralogoff handle_conexion

Oraclose cierra un cursor a la base de datos, mientras que oralogoff cierra la conexión con la base.

De esta forma, una consulta a la base de datos se haría de la siguiente manera.
# Abre la conexion con la base.
set handle [oralogon pepe/pepe@T:afrodita:SIO]
# Abre un cursor a la base.
ser cursor [oraopen $handle]
# Se harian aqui las consultas....
.
.
# Se cierran los cursores.
oraclose $cursor
# Se cierra la conexion.
oralogoff $handle

De todas formas, no es estrictamente necesario utilizar simultáneamente oraclose y oralogoff, bastará con utilizar oralogoff, ya que además de cerrar una conexión a la base, cierra todos los cursores relacionados con dicha conexión.

Pero una base de datos no está sólo para abrir conexiones y cerrarlas. Como su propio nombre indica, deberá poder accederse a los datos en ella almacenados. Esto se consigue con el comando orasql.

orasql cursor_conexion sentencia_sql

Orasql le pasa al servidor de Oracle una sentencia SQL. Por ejemplo:

orasql $cursor "select * from emp where ename like \
‘${searchname}’ "

Orasql causará un error si el servidor de Oracle rechaza la petición SQL, debido a una sintaxis errónea o porque la sentencia SQL hace referencia a tablas o columnas que no existen. Es recomendable utilizar orasql dentro de una sentencia catch, de forma que se pueda recuperar el error en caso de producirse.

Si el servidor de Oracle ha recibido una sentencia SQL correcta devolverá "0". En caso contrario se producirá un error. El número de error de Oracle se encontrará en $oramsg(rc), y la descripción del error en $oramsg(errortxt).

Una vez hecha la petición de datos, estos deben ser recuperados de la base, para ello se utilizará el comando orafetch.

orafetch cursor_conexion ?sentencia_tcl?

Este comando obtiene la siguiente fila disponible en la base, y devuelve el resultado como una lista Tcl. Los elementos de la lista se corresponden con las columnas seleccionadas en el mismo orden en que se dispusieron en la sentencia SQL del comando orasql.


# Se piden los datos.
orasql $cursor "select * from emp"
# Se recuperan los datos.
set col [orafetch $cursor]
# Se muestra por pantalla el resultado.
puts "Numero de columnas : [llength $col]"
puts "La primera columna es : [lindex $col 0]

Orafetch comvierte cualquier tipo de dato en cadena para adecuarse al modelo de datos de Tcl. Cada ejecución de orafetch devolverá la siguiente fila. Además, orafetch colocará en la variable $oramsg(rc) un número que indicará lo que ha devuelto. Los valores típicos son:

Tabla B-2. Valores típicos de $oramsg(rc) con orafetch.

0

Se ha devuelto una fila.

1403

Se ha encontrado el finalde las filas.

Uno de los principales problemas al acceder a bases de datos para recuperar gran número de ellos, es el tiempo de acceso exageradamente elevado; mayor aún si la base tiene que realizar operaciones con los datos, tales como medias, máximos, mínimos, etc.

Frente a este tiempo, la lentitud propia de Tcl (lógica si se tiene en cuenta que es un lenguaje interpretado) no tiene mayor importancia por regla general.

Pero sí existe un caso donde es posible ganar tiempo. Este es en el bucle while que se utiliza para ir recorriendo la tabla, y haciendo orafetch sucesivos. Un ejemplo de esto es:


orasql $cursor "select ename, hiredate from emp"
# Se obtiene la primera columna.
set col [orafetch $cursor]
# Se recorre el resto de columnas.
# Mientras no se haya llegado a la última...
while {oramsg(rc) == 0} {
puts [format "%-15.15s %s" \
[lindex $col 0] [lindex $col 1]
set col [orafetch $cursor]
}

Como puede verse, hacer este bucle while en Tcl supone peder mucho tiempo debido a la baja velocidad de Tcl. La versión actual de Oratcl mejora esto, ya que este bucle que hasta este momento se venía haciendo en Tcl, ahora lo realiza la propia Oratcl en su código en C, por lo que la velocidad es muy superior. El nuevo código será:


orasql $cursor "select ename, hiredate from emp"
# Se obtienen todas las columnas.
orafetch $cursor { puts \
[format "%-15.15s %s" @1 @2]}

En esta versión se hace referencia a las columnas de cada fila mediante una notación especial, utilizando el prefijo "@ ". De esta forma @ 1 se refiere a la primera columna, @ 2 a la segunda , y así sucesivamente. Por su parte @ 0 es la fila completa como una lista Tcl, tal como orafetch normalmente devuelve los datos. No existe límite para el número de veces que una columna es especificada, ni para el número de sentencias Tcl que se ejecutarán dentro del bucle.

Es importante saber que esta notación no admite algo como esto:

@ {$i}

Estos son los comandos Oratcl más básicos. Además de estos existen otros, igual de elementales, pero menos usados. Son los siguientes:

oracols cursor_conexion

Oracols se utiliza después de orasql o de orafetch. Este comando devuelve los nombres de las columnas en el mismo orden en que se devuelven los datos por medio de orafetch.

A parte de esto, la ejecución de oracols, coloca en el el array $oramsg los typos de datos de cada columna y la longitud. esto lo hace en los elementos $oramsg(coltypes) y $oramsg(collengths).

oracancel cursor_conexion

Este comando informa al servidor que ciertas filas que estaban pendientes desde el ultimo orasql, han sido descartadas. El comando orasql siempre ejecuta un oracancel al final de cada ejecución de una sentencia SQL.

oracommit handle_conexion

Este comando hace visible para todos los usuarios los cambios provocados por un usuario.

oraroll handle_conexion

El comando oraroll deshace todos los cambios efectuados por un usuario desde el último oracommit.

oraautocom handle_conexion on_o_off

Admite dos posiciones, on u off. Si está en situación on, cada cambio en la base de datos (insert, update o delete) es visible para el resto de usuarios de forma inmediate, sin necesidad de utilizar oracommit. Por defecto su valor es off.


El array $oramsg

Como ya se comentó al inicio de este apéndice, Oratcl añade a Tcl, además de los comandos de acceso a la base de datos Oracle, un array de carácter global, oramsg. Este array es mantenido y utilizado por Oratcl para almacenar información acerca del servidor de Oracle, y controlar varios aspectos de Oratcl. La tabla B-3 resume los elementos de este array.

Tabla B-3. Elementos del array $oramsg.

$oramsg(nullvalue)

Controla cómo Oratcl representa las columnas que contienen NULL, cuando son recibidas mediante orafetch. Por defecto el valor es default, el cual convierte los tipos de datos numéricos en 0, y los demás en una cadena "".

$oramsg(maxlong)

Limita la longitud de los datos recibidos por orafetch. El límite por defecto es 32768 bytes. Es posible darle el máximo valor que admite Oracle: 2147483647

$oramsg(handle)

Devuelve el handle o cursor del último comando de Oratcl ejecutado.

$oramsg(rc)

rc es el código de retorno de la librería OCI. Los valores más comunes son:

0 Función completada sin error.

900-999 Sentencia SQL inválida, nombre de columna incorrecto, etc.

1000-1099 Conexión denegada, privilegios insuficientes, etc.

1400-1499 Error de ejecución SQL.

1403 Fin de las filas buscadas por orafetch.

1406 orafetch ha truncado un columna demasiado larga

$oramsg(errortxt)

Es un mensaje que describe el error producido. Está asociado al código rc.

$oramsg(collengths)

Es una lista Tcl de longitudes de las columnas que se corresponden con los nombres de las columnas devueltos por oracols.

$oramsg(coltypes)

Es una lista Tcl de los tipos de datos de las columnas, que se corresponden con los nombres de columnas devueltos por oracols. Tanto esta como la anterior sólo serán asignadas por Oratcl después de haber sido ejecutado oracols.

$oramsg(colprecs)

Es también una lista Tcl que indica la precisión numérica de los datos de cada columna. Se corresponde con los nombres de columnas devueltos por oracols. Para datos no numéricos, este elemento es una cadena vacía.

$oramsg(colscales)

Lista Tcl de las escalas de los valores numéricos de los datos de las columnas. Se corresponden con los nombres devueltos por oracols.

$oramsg(sqlfunc)

Es el código numérico del último comando SQL ejecutado. Los códigos más comunes son: 3 (insert), 4 (select), 5 (update), 9 (delete).

$oramsg(ocifunc)

Es el código numérico de la última función OCI ejecutada.

$oramsg(rows)

Es el número de filas afectadas por un comando SQL del tipo insert, update o delete, o el número acumulativo de filas con las que orafetch ha trabajado.


Capturando errores

Los comandos de Oratcl generan un error cuando dicho comando es inválido, o cuando el servidor de Oracle considera errónea alguna sentencia SQL.

El intérprete de Tcl, normalmente, detiene la ejecución del programa cuando se produce un error. Sin embargo el comando de Tcl catch permite capturar el error y mostrarlo sin que la ejecución se aborte.

Por ejemplo, el comando oralogon produce un error cuando el nombre de usuario o el password son incorrectos, o el servidor de Oracle no está disponible. Con el comando catch es posible capturar este error:


if [catch {oralogon ${userid}/${passwd} } handle] {
puts "No es posible acceder al servidor, debido a $oramsg(errortxt)"
exit
}

Previous Page Next Page


© 1995-98, etsimo WWW team
Última modificación: 19 de Agosto de 1998 - 17:51:15