Seite 1 von 1

MySQLdb: INSERT

Verfasst: Sonntag 5. Juli 2009, 22:32
von gerald
Hallo!

Ich probiere gerade einzelne Zeilen in eine MySQL-Tabelle einzufügen, stoße dabei aber auf einige Probleme :?

Code: Alles auswählen

import cmd
import MySQLdb
import getpass

db = MySQLdb.connect("localhost", "benutzername", "password", "datenbank")
c = db.cursor()

class ManagementKonsole(cmd.Cmd):

    def __init__(self):
        cmd.Cmd.__init__(self)
        self.prompt = ">>> "

    def do_adduser(self, prm):
        username = raw_input("Username: ")
        password = getpass.getpass("Password: ")

        c.execute('''
                INSERT INTO login (id, username, password)
                VALUES (%(id)s, %(username)s), %(password)s
                ''', {
                'id': None,
                'username': username,
                'password': password
                })

    def do_showuser(self, prm):
        weitere Anweisungen

    def do_exit(self, prm):
        return True

    def do_quit(self, prm):
        return True

konsole = ManagementKonsole()
konsole.cmdloop()
Speziell geht es bei mir um die Zeile "def do_adduser(self, prm):". Dort erhalte ich folgende Fehlermeldung:
gerald@lisa:~/verwaltung$ python console.py
>>> adduser
Username: gerald
Password: verdeckt eingegebenes Kennwort dank getpass ;-)
Traceback (most recent call last):
File "console.py", line 39, in <module>
konsole.cmdloop()
File "/usr/lib/python2.5/cmd.py", line 142, in cmdloop
stop = self.onecmd(line)
File "/usr/lib/python2.5/cmd.py", line 219, in onecmd
return func(arg)
File "console.py", line 24, in do_adduser
'password': password
File "/var/lib/python-support/python2.5/MySQLdb/cursors.py", line 166, in execute
self.errorhandler(self, exc, value)
File "/var/lib/python-support/python2.5/MySQLdb/connections.py", line 35, in defaulterrorhandler
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 ''test'' at line 2")
Ich verwende ein Debian lenny mit MySQLdb in jeweils aktuellem Stand.
Weiß einer bei meinem Problem weiter?

Schönen Abend noch,
gerald

Verfasst: Sonntag 5. Juli 2009, 23:11
von BlackJack
Tja, die Fehlermeldung sagt, dass die SQL-Syntax fehlerhaft ist. Das ist sie auch in der Tat. Schau mal wo die schliessende Klammer zu der öffnenden gleich nach 'VALUES' ist.

Verfasst: Sonntag 5. Juli 2009, 23:17
von derdon
Ich habe das Gefühl, du versuchst SQLAlchemy Console (deines ist an MySQL gebunden und hat keine farbige Ausgabe) nachzubauen.

Verfasst: Sonntag 5. Juli 2009, 23:56
von gerald
Vielen Dank erstmal für die Antworten!
BlackJack hat geschrieben:Tja, die Fehlermeldung sagt, dass die SQL-Syntax fehlerhaft ist. Das ist sie auch in der Tat. Schau mal wo die schliessende Klammer zu der öffnenden gleich nach 'VALUES' ist.
Okay, das ist aus der Fehlermeldung ersichtlich, aber den Fehler habe ich daraus trotzdem nicht gefunden ;-)
derdon hat geschrieben:Ich habe das Gefühl, du versuchst SQLAlchemy Console (deines ist an MySQL gebunden und hat keine farbige Ausgabe) nachzubauen.
Kann gut sein, ich habe halt nach allen möglichen gesucht, daher will ich nicht ausschließen, dass der Ansatz komplett falsch ist.

Ich habe jetzt aus MySQLdb User's Guide das Beispiel

Code: Alles auswählen

c.executemany(
      """INSERT INTO breakfast (name, spam, eggs, sausage, price)
      VALUES (%s, %s, %s, %s, %s)""",
      [
      ("Spam and Sausage Lover's Plate", 5, 1, 8, 7.95 ),
      ("Not So Much Spam Plate", 3, 2, 0, 3.95 ),
      ("Don't Wany ANY SPAM! Plate", 0, 4, 3, 5.95 )
      ] )
herausgesucht und versucht anzupassen:

Code: Alles auswählen

        c.execute(
                """INSERT INTO login (id, username, password)
                VALUES (%s, %s, %s)""",
                [
                ("", username, password )
                ] )
Aber auch dabei erhalte ich Fehlermeldungen:
>>> adduser
Username: gerald
Password:
Traceback (most recent call last):
File "console.py", line 37, in <module>
konsole.cmdloop()
File "/usr/lib/python2.5/cmd.py", line 142, in cmdloop
stop = self.onecmd(line)
File "/usr/lib/python2.5/cmd.py", line 219, in onecmd
return func(arg)
File "console.py", line 22, in do_adduser
("", username, password )
File "/var/lib/python-support/python2.5/MySQLdb/cursors.py", line 151, in execute
query = query % db.literal(args)
TypeError: not enough arguments for format string
Mir ist leider überhaupt nicht klar, wo der Fehler in Zeile 22 stecken soll (das ist bei mir --("", username, password )--) Hat vielleicht noch jemand eine Idee?

EDIT: Vielleicht ist es ja ("", nur habe ich dafür ansonsten keine andere Lösung, None brachte die selbe Fehlermeldung. Die Spalte id in der Datenbank ist mit auto_increment versehen, d.h. die laufende Nummer soll automatisch eingesetzt werden.

Verfasst: Montag 6. Juli 2009, 05:49
von sehbaer
Autoincrement Spalten weist man keine Werte zu. Auch kein "" oder sowas. Dafür ist es ja Autoincrement. Einfach die Zuweisung auf id entfernen.

Verfasst: Montag 6. Juli 2009, 07:01
von BlackJack
@gerald: `execute()` != `executemany()`.

Verfasst: Montag 6. Juli 2009, 10:33
von gerald
sehbaer hat geschrieben:Autoincrement Spalten weist man keine Werte zu. Auch kein "" oder sowas. Dafür ist es ja Autoincrement. Einfach die Zuweisung auf id entfernen.
Ah okay, das ist warscheinlich noch eine Angewohnheit aus PHP-Zeiten, da habe ich es so gemacht und es hat auch so funktioniert ;-)
BlackJack hat geschrieben:@gerald: `execute()` != `executemany()`.
Hm, dann habe ich die Doku zu MySQLdb falsch verstanden, ich habe gedacht, dass man execute() bei einem Datensatz und executemany() bei mehreren Datensätzen nutzt. Ich habe nun executemany() verwendet und von sehbaer den Tipp mit auto increment beachtet. Erster Erfolg: Ich erhalte keine Fehlermeldungen mehr, aber trotzdem wird nichts in die Tabelle geschrieben :shock:

Zur Vollständigkeit nochmal der Code:

Code: Alles auswählen

import cmd
import MySQLdb
import getpass

db = MySQLdb.connect("localhost", "username", "password", "datenbank")
c = db.cursor()

class ManagementKonsole(cmd.Cmd):

    def __init__(self):
        cmd.Cmd.__init__(self)
        self.prompt = ">>> "

    def do_adduser(self, prm):
        username = raw_input("Username: ")
        password = getpass.getpass("Password: ")

        c.executemany(
                """INSERT INTO login (username, password)
                VALUES (%s, %s)""",
                [
                (username, password )
                ] )

    def do_showusers(self, prm):
        username = raw_input("Username: ")
        c.execute("SELECT * FROM login WHERE username = %s", (username,))
        print c.fetchall()

    def do_exit(self, prm):
        return True

    def do_quit(self, prm):
        return True

konsole = ManagementKonsole()
konsole.cmdloop()
EDIT: Ich sehe, dass die ID aus auto_increment steigt, das heißt, dass diese schonmal richtig übermittelt wird...

Verfasst: Montag 6. Juli 2009, 11:01
von BlackJack
@gerald: Deine Beschreibung der beiden Methoden ist schon richtig, aber Du hast dann versucht `execute()` mit mehreren Datensätzen zu benutzen. Beziehungsweise eigentlich nur mit einem, dem aber dann in einer Liste, so wie Du das jetzt mit `executemany()` machst. Was unsinnig ist, wenn da sowieso immer nur ein Datensatz steht.