- Introducción
- Instalando el cliente de ORACLE
- Compilando la extensión cx_Oracle
- Probando una consulta
- Retornando un valor
- Haciendo un insert
- Referencias
Introducción
En este documento se muestra como realizar una consulta a una base de datos usando el motor ORACLE, desde el lenguaje de programación Python.
Seguramente hay varias opciones para esto. En este documento se usa el Instant Client. Las instrucciones fueron probadas en Debian GNU/Linux. Es probable que sean útiles para Ubuntu y para otras distribuciones.
El documento fue escrito inicialmente por Nelson. Recuerde esta es una Wiki, por lo que si ve errores en este documento, puede editar y corregirlos.
Es mejor usar una base de datos con código fuente libre (como PostgreSQL o MySQL), pero si la mejor opción es ORACLE (o la que toca implementar) acá hay unas instrucciones que pueden ser útiles.
Instalando el cliente de ORACLE
El primer paso es bajar el Instant Client de ORACLE (requiere registro gratuito). Los archivos del cliente se descomprimen en un directorio. En este ejemplo, usaremos la variable de entorno $INSTANT para denotar el $PATH en el que se descomprimen. Se requiere usar el paquete unzip.
$ unzip instantclient-basic-linux32-10.2.0.3-20061115.zip Archive: instantclient-basic-linux32-10.2.0.3-20061115.zip inflating: instantclient_10_2/classes12.jar inflating: instantclient_10_2/genezi #más archivos...
El kit de desarrollo:
$ unzip instantclient-sdk-linux32-10.2.0.3-20061115.zip Archive: instantclient-sdk-linux32-10.2.0.3-20061115.zip creating: instantclient_10_2/sdk/ creating: instantclient_10_2/sdk/include/ inflating: instantclient_10_2/sdk/include/occi.h inflating: instantclient_10_2/sdk/include/occiCommon.h #más archivos
Ahora instanciamos la variable de entorno $INSTANT, que usamos para hacer que estas instrucciones no dependan de la ruta específica de la instalación.
export INSTANT=/$HOME/python-oracle/instantclient_10_2/
Compilando la extensión cx_Oracle
Ahora se descarga la extensión cx_Oracle, que permite realizar la conexión a la base de datos desde Python. Se requiere instalar el paquete python-dev.
sudo aptitude install python-dev
# Es necesario poner este enlace para que funcione la compilación. Si no, sale el error # /usr/bin/ld: cannot find -lclntsh pushd $INSTANT && ln -s libclntsh.so.10.1 libclntsh.so && popd
export ORACLE_HOME=$INSTANT tar xzvf cx_Oracle-X.X.X.tar.gz # la extensión bajada (probamos con la versión 4.3.1) cd cx_Oracle-X.X.X python setup.py build
Al terminar la compilación, la extensión compilada queda en el directorio cx_Oracle-X.X.X/build/lib.linux-i686-2.4/ y el nombre del archivo es cx_Oracle.so. El nombre del directorio depende de su plataforma. Para probarla se puede instalar para que esté disponible para todos los usuarios del sistema (ejecutando Python python setup.py install como root).
Haremos la prueba sin instalar la extensión. La copiaremos a la ruta en la que se va a incluir.
LD_LIBRARY_PATH=$INSTANT ./test.py cp cx_Oracle-X.X.X/build/lib.linux-i686-2.4/cx_Oracle.so .
Probando una consulta
El siguiente es el código de un archivo que llamaremos test.py:
#!/usr/bin/env python
import cx_Oracle, sys
dsn = cx_Oracle.makedsn('127.0.0.1', 1521, 'BASEDATOS')
connection = cx_Oracle.connect('USUARIO', 'PASSWORD', dsn)
cursor = connection.cursor()
cursor = connection.cursor()
cursor.arraysize = 50
cursor.execute("""select columna1, columna2 from tabla where rownum < :arg_1""", arg_1 = 3)
for c1, c2 in cursor.fetchall():
print 'Values:', c1, c2
Para ejecutar el script, se requiere tener asignadas las variables de entorno LD_LIBRARY_PATH y ORACLE_HOME. Este el resultado de la prueba:
$ ORACLE_HOME=$INSTANT LD_LIBRARY_PATH=$INSTANT python test.py Values: 514 985 Values: 379 1038
Retornando un valor
En este mensaje hay un ejemplo en el que explican como retornar un valor, y esto es útil en ciertos casos. Por ejemplo en el siguiente ejemplo se requiere el valor de una secuencia, de las que se usan como claves primarias.
idVar = cursor.var(cx_Oracle.NUMBER)
q = """BEGIN
select carg_arch.CAR_ARCH_ARCHIVOS_SECUE.nextval into :id from dual;
END;"""
cursor.execute(q, id = idVar)
print idVar.getvalue()
TODO: ¿Es esto realmente necesario? ¿Hay un atajo?.
Haciendo un insert
q = "insert into table(fielda, fieldb) values(:idx, 'something')"; cursor.execute(q, idx=2) connection.commit()
No olvide hacer el commit.
Referencias
- http://www.oracle.com/technology/pub/articles/devlin-python-oracle.html
- http://sourceforge.net/projects/cx-oracle/
- http://www.orablogs.com/sergio/archives/001871.html
Last update: 2007-06-12 (Rev 11659)