Benutzer-Werkzeuge

Webseiten-Werkzeuge


python:python_database

Python 2.7 / 3.4 und die Oracle Datenbank

Mit der cx_Oracle (http://cx-oracle.sourceforge.net/) Library lässt sich einfach die Oracle Datenbank in Python einbinden.

Voraussetzung

Eine Oracle OCI Client Umgebung in der richtigen Bit Version und Oracle Version ist installiert!

Minimal ist dazu der „Oracle Instant Client“ notwendig, siehe ⇒ http://www.oracle.com/technetwork/database/features/instant-client/index-097480.html

In vielen Beispielen im Netz werden keine Bind Variablen verwendet, davon ist dringend abzuraten!

D.h. die SQL Statements werden als String Objekte „zusammen gebaut“ und dann ausgeführt!

Das ist eine der Hauptursachen für die ganzen SQL Injektion Problem in vielen Anwendungen!

Mehr dazu siehe hier: Alexander Kornbrust -Tutorial: Oracle SQL Injection in Webapps – Part I

Installation Windows 10

Für Windows kann die Software mit einem Installer installiert werden.

Software download für Python 2.7 und 3.4 32bit für eine 11g Client 32bit Umgebung

Die neueste Python Library für die Oracle Datenbank von https://pypi.python.org/pypi/cx_Oracle landen

  • cx_Oracle-5.2-11g.win32-py2.7-2.exe (md5) (md5 ⇒ 94a2b3dd0922f07d613ed1b67a14b48c)
  • cx_Oracle-5.2-11g.win32-py3.4.exe (md5) (md5 ⇒ 63137306c4fd292438a693dbce0a801d)

Auf die Bit Version achten! In meine Fall 32bit und 11g!

Datei prüfen und installieren

Über die Powershell MD5 checken:

cd C:\Users\gpipperr\Downloads
 
 
[Reflection.Assembly]::LoadWithPartialName("System.Web")
 
[System.Web.Security.FormsAuthentication]::HashPasswordForStoringInConfigFile("cx_Oracle-5.2-11g.win32-py2.7-2.exe","MD5")
 
67413C94BA8BCFD462315787CDCFE7BA

Toll, dies ist mal ein ganz anderer Hash als auf der Webseite angegeben …

Installer starten, und Library im jeweilgen Python Home installieren

Installation mit pip

Leider funktioniert mit installierten C++ Compiler (Fehler „error: Microsoft Visual C++ 10.0 is required (Unable to find vcvarsall.bat).“ )

.\python.exe -m pip install cx_Oracle

Installation Cygwin Windows 7

Voraussetzung:

  • Oracle Client auf dem System installiert
  • gcc unter cywin

Download der Sourcen

Wieder über ⇒ https://pypi.python.org/pypi/cx_Oracle

  • cx_Oracle-5.1.3.tar.gz (md5) ⇒ 32491c97d099d6ed04fd686697e3a6ea

Nach cygwin /tmp kopieren + MD5 Testen und entpacken:

md5sum cx_Oracle-5.1.3.tar.gz
cd6ff16559cbc9c20087ec812c7092ab *cx_Oracle-5.1.3.tar.gz
 
tar xfvz cx_Oracle-5.1.3.tar.gz
 
 
cd ./cx_Oracle-5.1.3

Übersetzen und installieren

# in das ausgepackte Verzeichnis wechseln
cd /tmp/cx_Oracle-5.1.3
 
 
python setup.py  build
 
#Fehler 
 
gcc: Fehler: nicht erkannte Kommandozeilenoption »-mno-cygwin«
error: command 'gcc' failed with exit status
 
vi setup.py
..
#nach mno-cygwin suchen und auskomentieren
....
elif sys.platform == "cygwin":
    #extraCompileArgs.append("-mno-cygwin")
 
..
 
 
# erneut aufrufen =>
python setup.py  build
 
cx_Oracle.c:10:17: schwerwiegender Fehler: oci.h: No such file or directory
 #include <oci.h>
                 ^
 
# Oracle Home setzen  aufgerufen
 
export ORACLE_HOME=/cygdrive/d/oracle/product/11.2.0.3/dbhome_1
 
 
python setup.py  build
 
python setup.py  install
 
 
#Warnings ignorieren 
 
#ok!
 
#teste mit Script weiter unten

Test 1 - die EMP Tabelle abfragen

Die EMP Tabelle abfragen:

import cx_Oracle
 
# get client library version
print "Oracle Client Library Version :: ", cx_Oracle.clientversion()
 
#get the connection to the database
connection = cx_Oracle.connect('scott/tiger@10.10.10.1/GPI')
 
# Version der DB ausgeben
print "Oracle Database Version ::", connection.version
 
#Cursor auf die DB öffenen
 
cursor = connection.cursor()
 
#Cursor ausführen
cursor.execute('select * from emp order by empno')
 
 
# Ergebnis ausgeben:
# simple
#for result in cursor:
#   print result
 
 
# extended fetch
#
for EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO in cursor.fetchall():
    print "Values from DB:", EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO
 
 
#Verbindung wieder schließen
cursor.close()
connection.close()

Problem: ORA-12557: TNS:protocol adapter not loadable

In einer Umgebung mit mehren Oracle Homes darauf achten das in der Umgebung keine Pfade gesetzt sind, die auf das andere Home als das gewünschte zeigen!

Test 2 - Mit Bind Variablen die EMP Tabelle abfragen

import cx_Oracle
 
connection = cx_Oracle.connect('scott/tiger@10.10.10.1/GPI')
 
# Cursor auf die DB oeffenen
cursor = connection.cursor()
 
# Cursor ausfuehren
cursor.prepare('select * from emp where deptno=:1')
 
# execute the statement on the statment above
# NONE Parameter
 
deptno = ("10", "20")
for i in deptno:
    cursor.execute(None, {'1': i})
    result = cursor.fetchall()
    print result
 
 
 
#Verbindung wieder schliessen
cursor.close()
connection.close()

Test 3 - Daten in Tabelle EMP einfügen

import cx_Oracle
import sys
 
 
# get client library version
print "Oracle Client Library Version :: ", cx_Oracle.clientversion()
 
connection = cx_Oracle.connect('scott/tiger@10.10.10.1/GPI')
 
# Version der DB ausgeben
print "Oracle Database Version ::", connection.version
 
# Cursor auf die DB oeffenen
 
cursor = connection.cursor()
# Oracle dept table has this columns
# DEPTNO
# DNAME
# LOC
 
dept_rows = [(90, "London", "Headquarter" ), (92, "Muenich", "Support" )]
 
# how many rows to insert
cursor.bindarraysize = len(dept_rows)
 
# datatype - lenght of the inserted data
cursor.setinputsizes(int, 14, 13)
 
try:
    # insert the whole record
    cursor.executemany("insert into dept (DEPTNO, DNAME4,LOC) values (:1, :2,:3)", dept_rows)
except cx_Oracle.DatabaseError as e:
    connection.rollback()
    print "Oracle Database Error:", e
except:
    print "Unexpected error:", sys.exc_info()[0]
    raise
 
connection.commit()
 
 
# Verbindung wieder schliessen
cursor.close()
connection.close()

Test 4 - PL/SQL einbinden

Für das Einbinden von PL/SQL müssen die zurück gegeben Werte „gefangen“ werden können.

Procedure in PL/SQL anleegen:

CREATE OR REPLACE PROCEDURE myDate(p_date IN OUT DATE,p_offset NUMBER)
AS
BEGIN
p_date:=sysdate+p_offset;
END;
/

In Python aufrufen, auf die [] bei callproc achten:

import cx_Oracle
 
 
connection = cx_Oracle.connect('scott/tiger@10.10.10.1/GPI')
 
cursor = connection.cursor()
 
return_value = cursor.var(cx_Oracle.Date)
 
 
cursor.callproc('myDate', [return_value,2])
 
 
print return_value.getvalue()
 
 
# 
 
return_value = cursor.var(cx_Oracle.STRING)
 
cursor.execute(" BEGIN select sysdate into :1 from dual; END; ", [return_value])
 
print return_value.getvalue()
 
 
#close 
 
cursor.close()
connection.close()

Test 5 - DDL

import cx_Oracle
import sys
 
 
# get client library version
print "Oracle Client Library Version :: ", cx_Oracle.clientversion()
 
connection = cx_Oracle.connect('scott/tiger@10.10.10.1/GPI')
 
# Version der DB ausgeben
print "Oracle Database Version ::", connection.version
 
# Cursor auf die DB oeffenen
 
cursor = connection.cursor()
 
ddl_sql = "create table t7 ( id number(11) not null , texte varchar2(2000))"
 
try:
    cursor.execute(ddl_sql)
except cx_Oracle.DatabaseError as e:
    print "Oracle Database Error:", e
except:
    print "Unexpected error:", sys.exc_info()[0]
    raise
 
cursor.close()
 
# Verbindung wieder schliessen
connection.close()

Test 6 - Daten visualisieren mit matplotlib

matplotlib unter Windows

see ⇒ http://matplotlib.org

Vorbereitung ⇒ http://aka.ms/vcpython27 herunterladen und installieren (Microsoft Visual C++ Compiler for Python 2.7 )

python -m pip install matplotlib
Code Beispiel
# -*- coding: iso-8859-1 -*-
 
import cx_Oracle
 
import matplotlib.pyplot as plt
import numpy as np
 
# get client library version
print "Oracle Client Library Version :: ", cx_Oracle.clientversion()
 
connection = cx_Oracle.connect('scott/tiger@10.10.10.1/GPI')
 
# Version der DB ausgeben
print "Oracle Database Version ::", connection.version
 
#Cursor auf die DB öffenen
 
cursor = connection.cursor()
 
#Cursor ausführen
cursor.execute('select ename,sal from emp order by empno')
 
#exctract the values to plot
plot_values=[]
plot_names=[]
for ename,sal in cursor.fetchall():
    plot_values.append(sal)
    plot_names.append(ename)
 
 
################ Line Plot ##########
 
print plot_values
plt.plot(plot_values,'bs')
plt.show()
 
################ Bar diagramm #######
 
y_pos = np.arange(len(plot_names))
print y_pos
 
error = np.random.rand(len(plot_names))
print error
 
plt.barh(y_pos, plot_values, xerr=0, align='center', alpha=0.8)
 
plt.yticks(y_pos, plot_names)
 
plt.xlabel('Sallery')
plt.title('Enough for all?')
 
plt.show()
 
 
#Verbindung wieder schliessen
cursor.close()
connection.close()

Database Resident Connection Pooling (DRCP)

Quellen

Cookies helfen bei der Bereitstellung von Inhalten. Durch die Nutzung dieser Seiten erklären Sie sich damit einverstanden, dass Cookies auf Ihrem Rechner gespeichert werden. Weitere Information
"Autor: Gunther Pipperr"
python/python_database.txt · Zuletzt geändert: 2015/10/07 20:39 von Gunther Pippèrr