[Python-de] Oracle Datenbankabfrage mit like 'xx%'
Volker Helm
helm.volker at gmx.de
Mo Jun 18 08:05:45 UTC 2007
Hi,
>> Du wirst dir viel Nerven sparen - und viele unnötige Bugs in deinen
>> Skripten vermeiden, wenn du die Python DB-API mit der parametrisierten Form
>> von execute() verwendest, und generell vermeidest, SQL-Statements
>> "zusammenzustringen".
>>
>> con = cx_Oracle.connect(...)
>> cur = con.cursor()
>> cur.execute("""
>> select col1, col2 from artikel
>> where artikelnummer like :artikelnummer_pattern
>> """, artikelnummer_pattern="EV%")
>>
>> Leider finde ich kein Tutorial zu cx_Oracle, dass ich dir empfehlen könnte :-(
>>
Tutorial ist kaum nötig, die Dokumentation zusammen mit der Definition
der API ist nicht zu verachten.
Schau einfach auf http://www.python.org/doc/topics/database/ nach.
Bzgl. des Zugriffes auf die Datenbank würde ich wie folgt vorgehen:
1. Alle Variablen nicht per String zusammenflanschen, siehe obiges Beispiel
2. Alternative SQL "where" Bedingungen sollten fest kodiert sein und die
Variablen nachträglich über Parameter angefügt werden:
Hier mal ein Beispiel von mir für eine Adressabfrage:
[code]
def ad_get(self, betrieb, sart, scrit, begriff, loeid = False):
"""Liefert eine Liste der potentiellen Adressen zurück"""
err = 0
if loeid:
self.loeid = 1
else:
self.loeid = 0
self.ad_search_crit_inv = dict([(v, k) for k, v in
self.ad_search_crit.iteritems()])
ad_sql = """select distinct a.manr "Betrieb",
a.sart,
a.adrn "AdressNR",
a.vtrn "Vtr",
a.name sort,
decode(trim(a.vorname||a.name),null,'',
trim(a.vorname||' '||a.name)||chr(13))
||
trim(a.ergb||decode(ltrim(a.name3),null,'',chr(13)||a.name3)) "Name",
case when trim(a.psf) is not null or
trim(a.plzpsf) is not null
then trim('Postfach '||a.psf)
else trim(a.stra) end "Straße",
case when trim(a.psf) is not null and
trim(a.plzpsf) is not null
then trim(a.plzpsf)
else trim(a.plz) end "PLZ",
case when trim(a.psf) is not null and
trim(a.plzpsf) is not null
then nvl(trim(a.psfort),a.ort)
else trim(a.ort) end "Ort"
from t056ad a
where a.manr = :p_betrieb
and a.sart = :p_sart
and (a.vtrn!=:p_LOE or :p_loeid != 0)
%s
order by a.name, a.adrn"""
#entfernen des Suchkriteriums, falls vorhanden
print begriff,scrit
if begriff==None:
begriff = ''
elif len(begriff)>0:
if begriff[0] in self.ad_search_crit_inv:
scrit = begriff[0]
begriff = begriff[1:]
print begriff,scrit
#Säubern des Suchbegriffes
if len(begriff)>0:
begriff =
(begriff.lstrip('%')+'%').decode('utf8').encode(self.encoding).upper()
Vars = {'p_betrieb':betrieb, 'p_sart':sart, 'p_begriff':begriff,
'p_LOE':self.VTRN_LOE, 'p_loeid': self.loeid}
if scrit == self.ad_search_crit['Name']:
sql = """and upper(a.name) like :p_begriff"""
elif scrit == self.ad_search_crit['Telefon']:
sql = """and a.adrn in (select distinct k.adrn
from t042wkom k
where k.manr = a.manr
and k.sart = a.sart
and trim(k.telkz) is not null
and trim(k.nr) is not null
and
upper(replace(replace(replace(replace(k.nr,'/',''),'-',''),'
',''),'.','')) like :p_begriff)"""
else:
sql = """and a.adrn in (select distinct m.adrn
from t140amc m
where m.manr = a.manr
and m.sart = a.sart
and m.adrn = a.adrn
and m.maco like :p_begriff)"""
sql = ad_sql % sql
try:
cur = self.db.cursor()
cur.execute(sql, Vars)
result = cur
except:
err, result = 1, u"Keine Daten von
ad_get\n\tBetrieb\t%i\n\tSART\t%s\n\tSuchkriterium\t%s\n\tBegriff\t%s\n\tLöschkz\t%i"\
%(betrieb, sart, scrit, begriff, loeid)
return err, result
[/code]
Sieht recht kompliziert aus, findet aber je nach Vorgabe die Adresse
entsprechend des Namens, Telefonnummer oder Adressnummer.
Interessant ist die Zeile cur.execute(sql,Vars), diese nimmt den SQL und
die parametrisierten Variablen und verbindet sie. Die Variablen liegen
als Dictionary vor.
Hoffe, ich konnte helfen,
Volker