Seite 1 von 2

MySQL-Python-DB

Verfasst: Donnerstag 22. November 2007, 10:35
von fanus
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")

Verfasst: Donnerstag 22. November 2007, 10:55
von Y0Gi
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.

Verfasst: Donnerstag 22. November 2007, 11:05
von fanus
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)

Verfasst: Donnerstag 22. November 2007, 11:31
von BlackJack
Ja und Nein. Das kann funktionieren, muss es aber nicht. Siehe [wiki]Parametrisierte SQL-Queries[/wiki]

Verfasst: Donnerstag 22. November 2007, 13:54
von Leonidas
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.

Verfasst: Donnerstag 22. November 2007, 14:42
von Y0Gi
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.

Verfasst: Donnerstag 22. November 2007, 16:17
von fanus
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'})

Verfasst: Donnerstag 22. November 2007, 16:32
von Leonidas
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.

Verfasst: Donnerstag 22. November 2007, 16:49
von Y0Gi
Worauf beziehst du dich speziell?

Verfasst: Donnerstag 22. November 2007, 17:42
von Leonidas
Y0Gi hat geschrieben:Worauf beziehst du dich speziell?
Sorry, mein Fehler. Dieses Formatting sieht immer noch genauso aus. Hatte wohl was anderes im Kopf.

Verfasst: Freitag 23. November 2007, 15:03
von fanus
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) 

Verfasst: Freitag 23. November 2007, 15:49
von 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.

Verfasst: Freitag 23. November 2007, 17:00
von fanus
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

Verfasst: Freitag 23. November 2007, 17:19
von BlackJack
Na gut: Was um Himmels willen macht gerold denn da…

Verfasst: Freitag 23. November 2007, 18:21
von gerold
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
:-)

Verfasst: Montag 26. November 2007, 09:49
von fanus
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

Verfasst: Montag 26. November 2007, 14:39
von Y0Gi
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 ...`).

Verfasst: Montag 26. November 2007, 14:54
von fanus
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.

Verfasst: Mittwoch 28. November 2007, 08:42
von meneliel
Wenn ich das richtig verstanden habe, ist also eine Formatierung mit %s eher nicht zu empfehlen und man sollte lieber die pyformat Variante nehmen?

Verfasst: Mittwoch 28. November 2007, 09:16
von 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'))