Interactiunea cu Oracle Database din Python

Acest document prezintă conceptele fundamentale pentru interacțiunea cu o bază de date Oracle folosind limbajul de programare Python, bazat pe tutorialul "Python and Oracle Database Tutorial: The New Wave of Scripting".

Configurare Inițială

Pentru a putea realiza interacțiunea, e nevoie să fie instalat Python 3 (versiunea minimă depinde de sistemul de operare: 3.7+ pe Windows/macOS, 3.6+ pe Linux) și driverul python-oracledb; se poate instala folosind pip :

pip install oracledb --upgrade

De asemenea, e nevoie de acces la o instanță de Oracle Database, care poate fi locală sau la distanță.

Conectarea la Oracle

Conectarea la baza de date se face prin importarea modulului oracledb și utilizarea funcției connect(); pentru a introduce parola în mod securizat se recomanda modulul getpass :

import oracledb
import getpass

userpwd = getpass.getpass("Enter password: ")

connection = oracledb.connect(user="your_user", password=userpwd, dsn="172.30.240.13/your_user")
print("Database version:", connection.version)
connection.close()

Driverul suportă două moduri de operare: thin (implicit, fără necesitatea bibliotecilor client Oracle) și thick (necesită biblioteci client Oracle pentru funcționalități avansate) . Modul thick este activat prin apelarea funcției oracledb.init_oracle_client() .

Executarea Interogărilor și Preluarea Datelor

Pentru a executa interogări SQL, se creează un obiect cursor folosind metoda cursor() a conexiunii și apoi se utilizează metoda execute() pentru a rula interogarea:

cur = con.cursor()
cur.execute("select * from grupe order by grupa")
res = cur.fetchall()
for row in res:
    print(row)
cur.close()

Datele pot fi preluate folosind metode precum:

Performanța interogărilor poate fi îmbunătățită prin ajustarea parametrilor arraysize și prefetchrows ai cursorului. La final se închid conexiunile și cursoarele folosind metodele close() pentru a elibera resursele.

Legarea Datelor (Binding)

Utilizarea variabilelor de legare este esențială pentru reutilizarea instrucțiunilor SQL, îmbunătățirea performanței și prevenirea atacurilor de tip SQL injection . Legarea se poate face în interogări și în operațiuni de inserare:

# Legarea în interogări
sql = "select * from grupe where sectia = :v_sectia order by grupa"
cur.execute(sql, v_sectia='Informatica')
res = cur.fetchall()
print(res)
# Legarea în inserări (array binding cu executemany)
rows = [ (1, "First" ), (2, "Second" ) ]
cur.executemany("insert into mytab(id, data) values (:1, :2)", rows)

Funcționalitatea Batcherrors permite identificarea datelor invalide în timpul inserărilor multiple, fără a opri întregul proces.

Utilizarea PL/SQL

Python-oracledb permite interacțiunea cu proceduri și funcții stocate PL/SQL . Funcția callfunc() este utilizată pentru apelarea funcțiilor PL/SQL , iar metoda callproc() este utilizată pentru apelarea procedurilor PL/SQL . Pentru parametrii de ieșire ai procedurilor, se utilizează obiecte de tip variabilă cursor (cur.var()) .

# Apelarea unei funcții PL/SQL
res = cur.callfunc('myfunc', int, ('abc', 2))
print(res)
# Apelarea unei proceduri PL/SQL
myvar = cur.var(int)
cur.callproc('myproc', (123, myvar))
print(myvar.getvalue())

Gestionarea Tipurilor de Date (Type Handlers)

Type handlers permit modificarea modului în care datele sunt preluate din sau trimise către baza de date . Output type handlers (setați prin cursor.outputtypehandler sau connection.outputtypehandler) modifică tipul datelor preluate (e.g., numere ca șiruri de caractere) . Input type handlers (setați prin cursor.inputtypehandler) modifică modul în care datele sunt legate la instrucțiuni . Aceste mecanisme pot fi combinate cu convertori de variabile .

Lucrul cu Obiecte Mari (LOBs)

Python-oracledb oferă suport pentru lucrul cu obiecte mari (LOBs) precum CLOB (Character Large Object) și BLOB (Binary Large Object) . CLOB-urile pot fi preluate ca locatori (permițând citirea în bucăți folosind metodele size() și read()) sau direct ca șiruri de caractere prin setarea oracledb.defaults.fetch_lobs = False .

Funcții Rowfactory

Funcțiile rowfactory permit ca interogările să returneze obiecte diferite de tupluri, oferind acces la coloane prin nume. Modulul collections.namedtuple poate fi utilizat în acest scop .

import collections

cur.rowfactory = collections.namedtuple("MyClass", ["DeptNumber", "DeptName"])
rows = cur.fetchall()
for row in rows:
    print(row.DeptNumber, "->", row.DeptName)

Subclasa Conexiunilor și Cursoarelor

Subclasa claselor Connection și Cursor oferă posibilitatea de a personaliza comportamentul driverului, permițând "prinderea" momentelor de creare a conexiunii și a cursorului, logarea parametrilor și extinderea funcționalității.

Cursoare Derulabile (Scrollable Cursors)

În modul thick, cursoarele pot fi create ca derulabile, permițând navigarea înainte și înapoi prin setul de rezultate folosind metoda scroll() .

cur = con.cursor(scrollable=True)
cur.execute("select * from grupe order by grupa")
cur.scroll(2, mode="absolute") # go to second row
print(cur.fetchone())