Seite 1 von 2

Datum & SQL

Verfasst: Donnerstag 25. Juli 2013, 13:36
von Joe-Waschl
hi @ll,
habe leider ein kleines problem, und komme nicht weiter,
habe ein kleines skript geschrieben mit dem man adressen verwalten kann,
welche in eine datenbank in mysql gespeichert werden.
bei der funktion "alle" klappt die formatierung, nur
bei "namen" nicht :roll:
was mache ich falsch?

Code: Alles auswählen

def alle(db):
    cur = db.cursor() 
    #cur.execute("SELECT * FROM Anschrift")
    cur.execute("SELECT Anschrift_ID, Name, Nachname, Straße, PLZ, Ort, Telefon, Handy, email, DATE_FORMAT(Geburtstag, '%d.%m.%Y') AS Geburtstag FROM Anschrift;")
    for row in cur.fetchall():
        print '---------------------'
        print 'Nr.:       ', row[0]
        print 'Name:      ', row[1]
        print 'Nachname:  ', row[2]
        print 'Straße:    ', row[3]
        print 'PLZ:       ', row[4]
        print 'Ort:       ', row[5]
        print 'Telefonnr.:', row[6]
        print 'Handy:     ', row[7]
        print 'Email:     ', row[8]
        print 'Geburtstag:', row[9]
        print '----------------------'

def namen(db):
    eingabe = str(raw_input('Namen: '))
    cur = db.cursor()
    #cur.execute("SELECT * FROM Anschrift where Name = %s", (eingabe))
    cur.execute("SELECT Anschrift_ID, Nachname, Straße, PLZ, Ort, Telefon, Handy, email, DATE_FORMAT(Geburtstag, '%d.%m.%Y') AS Geburtstag FROM Anschrift where Name = '%s'", (eingabe))
    for row in cur.fetchall():
        print '---------------------'
        print 'Nr.:       ', row[0]
        print 'Name:      ', row[1]
        print 'Nachname:  ', row[2]
        print 'Straße:    ', row[3]
        print 'PLZ:       ', row[4]
        print 'Ort:       ', row[5]
        print 'Telefonnr.:', row[6]
        print 'Handy:     ', row[7]
        print 'Email:     ', row[8]
        print 'Geburtstag:', row[9]
        print '----------------------'
danke und gruß Joe

EDIT:
sry habe das wichtigste vergessen :oops:

Code: Alles auswählen

0 = Beenden
1 = alle anzeigen
2 = nach Namen Suchen
3 = Neuer Eintrag
4 = Löschen
Es sind: 1 Einträge vorhanden
eingabe: 2
Namen: Joe
Traceback (most recent call last):
  File "/home/user1/.eclipse/org.eclipse.platform_3.7.0_155965261/plugins/org.python.pydev_2.7.1.2012100913/pysrc/pydevd.py", line 1397, in <module>
    debugger.run(setup['file'], None, None)
  File "/home/user1/.eclipse/org.eclipse.platform_3.7.0_155965261/plugins/org.python.pydev_2.7.1.2012100913/pysrc/pydevd.py", line 1090, in run
    pydev_imports.execfile(file, globals, locals) #execute the script
  File "/home/user1/workspace/Datenbank/mysql/anschrieft.py", line 129, in <module>
    main()
  File "/home/user1/workspace/Datenbank/mysql/anschrieft.py", line 116, in main
    namen(db)
  File "/home/user1/workspace/Datenbank/mysql/anschrieft.py", line 38, in namen
    cur.execute("SELECT Anschrift_ID, Nachname, Straße, PLZ, Ort, Telefon, Handy, email, DATE_FORMAT(Geburtstag, '%d.%m.%Y') AS Geburtstag FROM Anschrift where Name = '%s'", (eingabe))
  File "/usr/lib/python2.7/dist-packages/MySQLdb/cursors.py", line 159, in execute
    query = query % db.literal(args)
TypeError: %d format: a number is required, not str

Re: Datum & SQL

Verfasst: Donnerstag 25. Juli 2013, 14:17
von Madmartigan
Was genau ist denn das Problem, also welchen Fehler erhälst du denn? Ich hab zwar keine wirkliche Erfahrung mit mySQL aber könnte mir vorstellen, dass dein Parameter nicht korrekt formatiert ist. Möglich, dass da eine Liste erwartet wird.

Ohne Fehlermeldung bleibt es aber beim blanken Rumraten. :wink:

Re: Datum & SQL

Verfasst: Donnerstag 25. Juli 2013, 18:44
von Joe-Waschl
EDIT

Re: Datum & SQL

Verfasst: Donnerstag 25. Juli 2013, 19:53
von lexaiden

Code: Alles auswählen

cur.execute("SELECT Anschrift_ID, Nachname, Straße, PLZ, Ort, Telefon, Handy, email, DATE_FORMAT(Geburtstag, '%d.%m.%Y') AS Geburtstag FROM Anschrift where Name = '%s'", (eingabe))
Das "eingabe" wird in das %d gepackt, würde ich jetzt mal so behaupten. Du solltest das anders schreiben, z.B. so:

Code: Alles auswählen

cur.execute("SELECT Anschrift_ID, Nachname, Straße, PLZ, Ort, Telefon, Handy, email, DATE_FORMAT(Geburtstag, '%d.%m.%Y') AS Geburtstag FROM Anschrift where Name = '" + str(eingabe) + "'")
Für alle die nur bis hier hin lesen, so gehts, aber so nicht machen. Siehe nächste Beiträge!

Re: Datum & SQL

Verfasst: Donnerstag 25. Juli 2013, 20:40
von BlackJack
@lexaiden: Nein, genau so etwas sollte man *nicht* machen. Das ist eine riesige Sicherheitslücke Benutzereingaben einfach so in eine SQL-Anfrage per Zeichenkettenoperationen zu stecken.

@Joe-Waschl: Du musst in der SQL-Anfrage die '%' schützen die nicht Teil von einem Platzhalter sind. Und statt dem einen Wert musst Du ein Tupel oder eine Liste mit `eingabe` als Element übergeben.

Re: Datum & SQL

Verfasst: Donnerstag 25. Juli 2013, 20:48
von lexaiden
@BlackJack Äh, richtig, ich hab nur die Fehlermeldung gelesen und die eine Zeile vom Code. Hab ich jetzt irgendwie vorrausgesetzt, dass dies keine Rohe Eingabe sein darf (bzw. ungeprüfte), aber steht da ja exakt so im Code... :shock:

Aber übersehe ich gerade was, dein Lösungsansatz ist doch genau das gleich und erlaubt SQL-Code für die Eingabe?!

Re: Datum & SQL

Verfasst: Donnerstag 25. Juli 2013, 20:50
von Joe-Waschl
thx, werds gleich probieren :)

EDIT:

mhhh nur wie schütze ich die % :K

Re: Datum & SQL

Verfasst: Donnerstag 25. Juli 2013, 20:54
von BlackJack
@lexaiden: Klar kann man SQL-Code eingeben, aber der wird vom Datenbankmodul entsprechend escaped, damit er als Wert und nicht als SQL-Ausdruck verwendet wird.

Re: Datum & SQL

Verfasst: Donnerstag 25. Juli 2013, 21:08
von lexaiden
@BlackJack Ach, das macht die "execute" Methode für mich. Sehr schön.

@Joe-Waschl
Note that any literal percent signs in the query string passed to execute() must be escaped, i.e. %%.
Parameter placeholders can only be used to insert column values. They can not be used for other parts of SQL, such as table names, statements, etc.
Quelle: http://mysql-python.sourceforge.net/MySQLdb.html

Re: Datum & SQL

Verfasst: Freitag 26. Juli 2013, 10:19
von Joe-Waschl
moin,

mit den doppelten prozent zeichen klappts leider auch nicht.

Code: Alles auswählen

namen(db):
    liste_eingabe = []
    eingabe = raw_input('Namen: ')
    liste_eingabe.append(eingabe)
    cur = db.cursor()
    cur.execute("""SELECT Anschrift_ID, Nachname, Straße, PLZ, Ort, Telefon, Handy, email, 
    DATE_FORMAT(Geburtstag, '%d.%m.%Y') AS Geburtstag FROM Anschrift where Name = '%%s'""", (liste_eingabe))
    #cur.execute("""SELECT Anschrift_ID, Nachname, Straße, PLZ, Ort, Telefon, Handy, email, 
    #DATE_FORMAT(Geburtstag, '%d.%m.%Y') AS Geburtstag FROM Anschrift where Name = '""" + liste_eingabe + "'")
    for row in cur.fetchall():
        print '---------------------'
        print 'Nr.:       ', row[0]
        print 'Name:      ', row[1]
        print 'Nachname:  ', row[2]
        print 'Straße:    ', row[3]
        print 'PLZ:       ', row[4]
        print 'Ort:       ', row[5]
        print 'Telefonnr.:', row[6]
        print 'Handy:     ', row[7]
        print 'Email:     ', row[8]
        print 'Geburtstag:', row[9]
        print '----------------------'
    
Fehlermeldung:

Code: Alles auswählen

Traceback (most recent call last):
  File "/home/user1/.eclipse/org.eclipse.platform_3.7.0_155965261/plugins/org.python.pydev_2.7.1.2012100913/pysrc/pydevd.py", line 1397, in <module>
    debugger.run(setup['file'], None, None)
  File "/home/user1/.eclipse/org.eclipse.platform_3.7.0_155965261/plugins/org.python.pydev_2.7.1.2012100913/pysrc/pydevd.py", line 1090, in run
    pydev_imports.execfile(file, globals, locals) #execute the script
  File "/home/user1/workspace/Datenbank/mysql/anschrieft.py", line 132, in <module>
    main()
  File "/home/user1/workspace/Datenbank/mysql/anschrieft.py", line 119, in main
    namen(db)
  File "/home/user1/workspace/Datenbank/mysql/anschrieft.py", line 40, in namen
    cur.execute("SELECT Anschrift_ID, Nachname, Straße, PLZ, Ort, Telefon, Handy, email, DATE_FORMAT(Geburtstag, '%d.%m.%Y') AS Geburtstag FROM Anschrift where Name = '%%s'", (liste_eingabe))
  File "/usr/lib/python2.7/dist-packages/MySQLdb/cursors.py", line 159, in execute
    query = query % db.literal(args)
TypeError: %d format: a number is required, not str
gruß Joe

Re: Datum & SQL

Verfasst: Freitag 26. Juli 2013, 11:23
von BlackJack
@Joe-Waschl: Du hast es ganau an der falschen Stelle gemacht. Nicht beim Platzhalter sondern bei den % wo *kein* Platzhalter stehen soll musst Du verdoppeln, damit die geschützt werden.

Re: Datum & SQL

Verfasst: Freitag 26. Juli 2013, 12:01
von Joe-Waschl
ahh ok thx :)

irgendwie steh ich auf der leitung :oops:

Code: Alles auswählen

cur.execute("""SELECT Anschrift_ID, Nachname, Straße, PLZ, Ort, Telefon, Handy, email, 
    DATE_FORMAT(Geburtstag, '%%d.%%m.%%Y') AS Geburtstag FROM Anschrift where Name = '%s'""", (liste_eingabe))

Code: Alles auswählen

Traceback (most recent call last):
  File "/home/user1/.eclipse/org.eclipse.platform_3.7.0_155965261/plugins/org.python.pydev_2.7.1.2012100913/pysrc/pydevd.py", line 1397, in <module>
    debugger.run(setup['file'], None, None)
  File "/home/user1/.eclipse/org.eclipse.platform_3.7.0_155965261/plugins/org.python.pydev_2.7.1.2012100913/pysrc/pydevd.py", line 1090, in run
    pydev_imports.execfile(file, globals, locals) #execute the script
  File "/home/user1/workspace/Datenbank/mysql/anschrieft.py", line 134, in <module>
    main()
  File "/home/user1/workspace/Datenbank/mysql/anschrieft.py", line 121, in main
    namen(db)
  File "/home/user1/workspace/Datenbank/mysql/anschrieft.py", line 41, in namen
    DATE_FORMAT(Geburtstag, '%%d.%%m.%%Y') AS Geburtstag FROM Anschrift where Name = '%s'""", (liste_eingabe))
  File "/usr/lib/python2.7/dist-packages/MySQLdb/cursors.py", line 174, in execute
    self.errorhandler(self, exc, value)
  File "/usr/lib/python2.7/dist-packages/MySQLdb/connections.py", line 36, 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 'Joe''' at line 2")

Re: Datum & SQL

Verfasst: Freitag 26. Juli 2013, 12:17
von BlackJack
@Joe-Waschl: Die ' um den Platzhalter gehören dort nicht hin.

Re: Datum & SQL

Verfasst: Freitag 26. Juli 2013, 12:48
von Joe-Waschl
ok :wink: thx

Code: Alles auswählen

print 'Geburtstag:', row[9]
IndexError: tuple index out of range
:K

Re: Datum & SQL

Verfasst: Freitag 26. Juli 2013, 12:51
von EyDu
Die Fehlermeldung sagt doch schon alles: du versuchst auf das 10. Element von row zuzugreifen, row hat aber keine 10 Elemente.

Re: Datum & SQL

Verfasst: Freitag 26. Juli 2013, 12:58
von Joe-Waschl
habs :oops: thx

Name hatte in der execute... gefehlt
...SELECT Anschrift_ID, Name, Nachname, Straße, PLZ, Ort, Telefon, Handy, email,
DATE_FORMAT(Geburtstag, '%%d.%%m.%%Y') AS Geburtstag FROM Anschrift where Name = %s...

danke für die hilfe :D

Re: Datum & SQL

Verfasst: Freitag 26. Juli 2013, 13:20
von BlackJack
@Joe-Waschl: Die beiden Funktionen enthalten zu viel fast identischen Code. So etwas sollte man vermeiden, weil es fehleranfällig ist wenn man mal etwas verändern will oder muss und das dann in jeder „Kopie” machen muss und auch auf die selbe Weise.

Das mit der Liste ist umständlich gelöst. Statt eine leere zu erstellen und dann ein einziges Element anzuhängen hätte man auch gleich eine literale Liste mit `eingabe` als einzigem Element hinschreiben können. Und das auch gleich als Argument beim `execute()`-Aufruf ohne es noch mal an einen Namen binden zu müssen. Die Klammern dort um die `eingabe` beziehungsweise `liste_eingabe` sind unnötig und sollten weggelassen werden.

Re: Datum & SQL

Verfasst: Freitag 26. Juli 2013, 13:36
von Joe-Waschl
habs geändert ;)

Code: Alles auswählen

def namen(db):
    eingabe = [raw_input('Namen: ')]
    cur = db.cursor()
    cur.execute("""SELECT Anschrift_ID, Name, Nachname, Straße, PLZ, Ort, Telefon, Handy, email, 
    DATE_FORMAT(Geburtstag, '%%d.%%m.%%Y') AS Geburtstag FROM Anschrift where Name = %s""", (eingabe))
    for row in cur.fetchall():
        print '---------------------'
        print 'Nr.:       ', row[0]
        print 'Name:      ', row[1]
        print 'Nachname:  ', row[2]
        print 'Straße:    ', row[3]
        print 'PLZ:       ', row[4]
        print 'Ort:       ', row[5]
        print 'Telefonnr.:', row[6]
        print 'Handy:     ', row[7]
        print 'Email:     ', row[8]
        print 'Geburtstag:', row[9]
        print '----------------------'

Re: Datum & SQL

Verfasst: Dienstag 30. Juli 2013, 15:45
von bfm
Joe-Waschl hat geschrieben:habs geändert ;)

Code: Alles auswählen

def namen(db):
    eingabe = [raw_input('Namen: ')]
    cur = db.cursor()
    cur.execute("""SELECT Anschrift_ID, Name, Nachname, Straße, PLZ, Ort, Telefon, Handy, email, 
    DATE_FORMAT(Geburtstag, '%%d.%%m.%%Y') AS Geburtstag FROM Anschrift where Name = %s""", (eingabe,))
    for row in cur.fetchall():
        print '---------------------'
        print 'Nr.:       ', row[0]
        print 'Name:      ', row[1]
        print 'Nachname:  ', row[2]
        print 'Straße:    ', row[3]
        print 'PLZ:       ', row[4]
        print 'Ort:       ', row[5]
        print 'Telefonnr.:', row[6]
        print 'Handy:     ', row[7]
        print 'Email:     ', row[8]
        print 'Geburtstag:', row[9]
        print '----------------------'
funktioniert die Abfrage so? Ich würde meinen, dass da hinter 'eingabe' noch das Komma fehlt, so wie ich es bereits geändert habe. Sonst übergibt man dem Platzhalter %s ein e dann ein i, n, g, a, b, e und nicht den Wert der in 'eingabe' gespeichert ist.

lg

Re: Datum & SQL

Verfasst: Dienstag 30. Juli 2013, 15:52
von BlackJack
@bfm: Da gehört weder das Komma noch die Klammern hin, weil Eingabe bereits eine Liste ist.