[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