MySQL-Python-DB

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
fanus
User
Beiträge: 46
Registriert: Dienstag 13. November 2007, 09:53

Hello liebe Leute,

ich hab das im Forum gefunden und wollts mal ausprobrieren. Kann mir jemand sagen, woran der Fehler liegt... ich verwende dazu ;MySQL und Pyton 2.5.1

LG

Code: Alles auswählen

    def OnCreate(self):
        
        sql = '''CREATE TABLE adressesTemp ( 
        id INTEGER PRIMARY KEY NOT NULL, 
        vorname VARCHAR(30), 
        zuname VARCHAR(40), 
        nachname VARCHAR(30), 
        anrede VARCHAR(20), 
        adresse VARCHAR(50), 
        plz VARCHAR(15), 
        ort VARCHAR(25), 
        land VARCHAR(30), 
        privatnummer VARCHAR(35), 
        privatfaxnummer VARCHAR(35), 
        mobilnummer VARCHAR(35), 
        bueronummer VARCHAR(35), 
        buerofaxnummer VARCHAR(35) 
    )''' 
            
        Cursor.execute(sql) 
        conn.commit ()

    def OnInsert(self,
                    vorname = None, zuname = None, nachname = None, anrede = None, adresse = None, plz = None, ort = None, land = None, 
                    privatnummer = None, privatfaxnummer = None, mobilnummer = None, bueronummer = None, buerofaxnummer = None 
                    ):
                    
        
        INSERT = '''INSERT INTO adressesTemp ( 
                vorname, 
                zuname, 
                nachname, 
                anrede, 
                adresse, 
                plz, 
                ort, 
                land, 
                privatnummer, 
                privatfaxnummer, 
                mobilnummer, 
                bueronummer, 
                buerofaxnummer 
            ) VALUES ( 
                :vorname, 
                :zuname, 
                :nachname, 
                :anrede, 
                :adresse, 
                :plz, 
                :ort, 
                :land, 
                :privatnummer, 
                :privatfaxnummer, 
                :mobilnummer, 
                :bueronummer, 
                :buerofaxnummer)''' 
         

        Cursor.execute(INSERT,{'vorname':vorname, 'zuname':zuname, 'nachname':nachname, 'anrede':anrede, 'adresse':adresse, 'plz':plz, 
                              'ort':ort, 'land':land, 'privatnummer':privatnummer, 'privatfaxnummer':privatfaxnummer, 
                              'mobilnummer':mobilnummer, 'bueronummer':bueronummer, 'buerofaxnummer':buerofaxnummer} 
                         ) 
                        
        Cursor.execute(sql) 
        conn.commit ()

Code: Alles auswählen

raise errorclass, errorvalue
_mysql_exceptions.ProgrammingError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ':vorname, \n :zuname, \n :nachname, \n ' at line 16")
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

MySQLdb verwendet keine ':platzhalter' und erwartet als Werte-Parameter für `.execute()` ein Dictionary, sondern behandelt '?' als Platzhalter und die Werte müssen als Sequenz (Tupel, Liste, ...) übergeben werden.
fanus
User
Beiträge: 46
Registriert: Dienstag 13. November 2007, 09:53

danke für die Antwort!
also wär doch das richtig gewesen?

Code: Alles auswählen

        INSERT= '''INSERT INTO adressesTemp ( 
                vorname, 
                zuname, 
                nachname, 
                anrede, 
                adresse, 
                plz, 
                ort, 
                land, 
                privatnummer, 
                privatfaxnummer, 
                mobilnummer, 
                bueronummer, 
                buerofaxnummer 
            ) VALUES ( 
                %s, 
                %s, 
                %s, 
                %s, 
                %s, 
                %s, 
                %s, 
                %s, 
                %s, 
                %s, 
                %s, 
                %s, 
                %s)''' % (vorname, zuname, nachname, anrede, adresse, plz, ort, land, 
privatnummer, privatfaxnummer, mobilnummer, bueronummer, buerofaxnummer)
BlackJack

Ja und Nein. Das kann funktionieren, muss es aber nicht. Siehe [wiki]Parametrisierte SQL-Queries[/wiki]
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

BlackJack hat geschrieben:Das kann funktionieren, muss es aber nicht.
Genau. Wenn man SQL-Injections unter "funktionieren" einstuft, dann funktioniert es sogar Klasse.
Also: SQL immer nur vom DB-Modul konstruieren lassen, selber-quoten ist in der Regel nicht sonderlich schlau.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Ups, ich meine natürlich auch '%s' (wie du offenbar richtig herausgefunden hast) und nicht '?' - da hab ich was mit einem anderen Wrapper verwechselt.

Der von BlackJack und Leonidas angesprochene feine, aber doch gravierende Unterschied liegt darin, dass bei der %-Formatierung über diesen Operator die Platzhalter zwar ersetzt werden, bei diesen aber nicht wie bei der zweiten Variante, die die Werte separat als Argument für `.execute()` erwartet, eine Maskierung von (potentiell gefährlichen) Zeichen vorgenommen wird.

Dies ist leider ein Schwachpunkt von '%s' als Platzhaltern, da er diesen Missbrauch ermöglicht und die wichtigen Grenzen der beiden (technischen) Möglichkeiten verwischt.
fanus
User
Beiträge: 46
Registriert: Dienstag 13. November 2007, 09:53

danke Leute!
ich habs grad so ausprobiert und es scheint zumindest zu funktionieren..

Code: Alles auswählen


        Cursor.execute( '''
                        INSERT INTO adressesTemp
                        (
                        id,
                        vorname, 
                        zuname, 
                        nachname, 
                        anrede, 
                        adresse, 
                        plz, 
                        ort, 
                        land, 
                        privatnummer, 
                        privatfaxnummer, 
                        mobilnummer, 
                        bueronummer, 
                        buerofaxnummer 
                        ) VALUES (
                        %(id)s, 
                        %(vorname)s, 
                        %(zuname)s, 
                        %(nachname)s, 
                        %(anrede)s, 
                        %(adresse)s, 
                        %(plz)s, 
                        %(ort)s, 
                        %(land)s, 
                        %(privatnummer)s, 
                        %(privatfaxnummer)s, 
                        %(mobilnummer)s, 
                        %(bueronummer)s,
                        %(buerofaxnummer)s
                        )
                        ''' ,{
                        'id':'555',
                        'vorname':'wir',
                        'zuname':'fahren',
                        'nachname':'zu',
                        'anrede':'der',
                        'adresse':'EM',
                        'plz':'2008',
                        'ort':'OHNE',
                        'land':'england',
                        'privatnummer':'0049111111',
                        'privatfaxnummer':'0049111111',
                        'mobilnummer':'0049111111',
                        'bueronummer':'0049111111',
                        'buerofaxnummer':'0049111111'})
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Y0Gi hat geschrieben:Dies ist leider ein Schwachpunkt von '%s' als Platzhaltern, da er diesen Missbrauch ermöglicht und die wichtigen Grenzen der beiden (technischen) Möglichkeiten verwischt.
Don't worry. Sieht in Python 3 etwas anders aus.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Worauf beziehst du dich speziell?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Y0Gi hat geschrieben:Worauf beziehst du dich speziell?
Sorry, mein Fehler. Dieses Formatting sieht immer noch genauso aus. Hatte wohl was anderes im Kopf.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
fanus
User
Beiträge: 46
Registriert: Dienstag 13. November 2007, 09:53

hi,

brauche ich bei MySQL auch so eine "try-except", wenn sowieso bei Eingabe falscher Daten einen Fehler gemeldet wird?

wenn ja was kommt denn nach "except" :oops:

LG,
fanus

Code: Alles auswählen

         try: 
             self.cur.execute(sql, locals()) 
             self.conn.commit() 
             return (True, "") 
         except sqlite3.IntegrityError, data: 
             return (False, data) 
BlackJack

Um Himmels willen was machst Du denn da. Das ``try``/``except`` gehört um den Code-Teil bei dem man im ``except``-Teil auch etwas sinnvolles in der Ausnahmesituation machen kann. Eine Ausnahme in einen Fehlerstatus umzuwandeln ist nicht sinnvoll, diesen Blödsinn sollen Ausnahmen ja gerade vermeiden.
fanus
User
Beiträge: 46
Registriert: Dienstag 13. November 2007, 09:53

das wurde 1 zu 1 aus diesem bsp genommen und wollte nur wissen wie ich das auf meine MySQL-DB anwenden kann. :roll:

http://gelb.bcom.at/trac/misc/browser/s ... rev=11#L99
BlackJack

Na gut: Was um Himmels willen macht gerold denn da…
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

BlackJack hat geschrieben:Na gut: Was um Himmels willen macht gerold denn da…
Hallo!

Sch... :roll:
Created: 2006-07-10
Ich wusste nicht dass das noch irgendwo verlinkt ist. Bitte nehmt das nicht als Beispiel her. Das war irgendwie eine nicht durchdachte Mitternachtsaktion, an der ich im Laufe von ein paar Tagen irgendetwas geändert habe, die ich aber nie fertig machte. Ich habe mich dabei (glaube ich noch zu wissen) in einer unschönen Codestruktur verrannt.

Das sollte ich eigentlich komplett löschen.

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
fanus
User
Beiträge: 46
Registriert: Dienstag 13. November 2007, 09:53

Hallo liebe Leute,

wie kann ich die in der DB gespeicherten Daten zurückgeben. Ich habs so versucht und kann leider nicht prüpfen ob das richtig ist oder nicht! :(

Code: Alles auswählen

Cursor.execute( ''' 
                        SELECT * FROM 
                            adressesTemp 
                        WHERE 
                            (
                            id = %(id)s
                            ) 
                            ''',
                            {
                            'id':ID
                            }
                            
                        )
        
        row = Cursor.fetchone ()
        if row: 
            return { 
                'id':row[0], 
                'vorname':row[1], 
               .
               .
               .

                'buerofaxnummer':row[12]
                } 
        else: 
            return None 
        
LG,
fanus
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Ist `Cursor` wirklich eine Instanz der Cursor-Klasse? Wenn ja, solltest du den Namen klein schreiben.

Gib doch testweise mal die erhaltenen Daten mit `print` aus.

Hier noch ein Tipp, wie man von MySQLdb Datensätze als Dictionaries zurück bekommt, so dass man auf die Attribute über ihre Namen zugreifen kann (was auch die Wartbarkeit der Anwendung enorm erhöht):

Code: Alles auswählen

import MySQLdb

conn = connect(...)  # insert your connection data
cursor = conn.cursor(MySQLdb.cursors.DictCursor)
Damit kannst du dann deinen gesamten Code ab Zeile 15 soweit verkürzen, dass er komplett durch ein `return cursor.fetchone()` ersetzt werden kann.

Außerdem ist `SELECT *` gerade bei späteren Schemaänderungen problematisch und sollte (ebenso wie Imports in Python) immer explizit die Namen der geforderten Elemente angeben (also etwa `SELECT id, vorname FROM ...`).
fanus
User
Beiträge: 46
Registriert: Dienstag 13. November 2007, 09:53

Y0Gi hat geschrieben:Ist `Cursor` wirklich eine Instanz der Cursor-Klasse? Wenn ja, solltest du den Namen klein schreiben.
sry da hab ich leider vertippt..

Gib doch testweise mal die erhaltenen Daten mit `print` aus.
es scheint so zu klappen..Danke!

Code: Alles auswählen

        while (1):
            row = cursor.fetchone ()
            if row == None:
                break
        print "%s, %s, %s, %s, %s" % (row[0], row[1], row[2], row[3], row[4] )
        

Außerdem ist `SELECT *` gerade bei späteren Schemaänderungen problematisch und sollte (ebenso wie Imports in Python) immer explizit die Namen der geforderten Elemente angeben (also etwa `SELECT id, vorname FROM ...`).
hab ich nicht gewusst...danke fuer den Tipp.
meneliel
User
Beiträge: 256
Registriert: Montag 25. Juni 2007, 08:35
Kontaktdaten:

Wenn ich das richtig verstanden habe, ist also eine Formatierung mit %s eher nicht zu empfehlen und man sollte lieber die pyformat Variante nehmen?
BlackJack

Nein man sollte das Einsetzen `execute()` überlassen, also:

Code: Alles auswählen

# Böse:
cursor.execute("INSERT INTO personen (vorname, nachname) VALUES ('%s', '%s')" %
               ("Max, 'x'); DROP TABLE personen; --", 'Mustermann'))

# Gut:
cursor.execute('INSERT INTO personen (vorname, nachname) VALUES (%s, %s)',
               ("Max, 'x'); DROP TABLE personen; --", 'Mustermann'))
Antworten