Seite 1 von 1
MySQL einzelne Daten ändern
Verfasst: Freitag 11. März 2011, 01:10
von Mathmos
Hi
Ich habe ein Problem beim Updaten einer Datenbank
Hiermit ermittle ich die Zeile die ich brauche
Code: Alles auswählen
topicID_auslesen = "SELECT * FROM webs_forum_topics WHERE topicID = %s" %(topicID)
Diese Zeile hat aber einige Spalten
(topicID, boardID, icon, intern, userID, date, topic, lastdate, lastposter, replys, views, closed, moveID, sticky)
Nun möchte ich die Einträge in "lastdate, lastposter, replys" ändern, wie muss ich da vorgehen?
Ich habe leider keine gescheites Beispiel finden können.
Re: MySQL einzelne Daten ändern
Verfasst: Freitag 11. März 2011, 01:26
von deets
Zum ersten, bitte verwende *nicht* den Code wie du ihn zeigst. Er ist hoch anfaellig fuer ein Sicherheitsleck das "SQL-Injection" heisst.
Um das zu umgehen sollte man unter *allen* Umstaenden die parametrisierte Variante von cursor.execute verwenden:
Code: Alles auswählen
cursor.execute("SELECT * FROM webs_forum_topics WHERE topicID = ?", (topicID))
Wie du siehst, musst du noch nicht mal viel aendern.
Und nun zu der eigentlichen Frage:
Code: Alles auswählen
cursor.execute("UPDATE webs_forum_topics SET lastdate=?, lastposter=?, replys=? WHERE topicID = ?", (ldate, lposter, replys, topicID))
Das ist aussem Kopp, aber sollte hinkommen.
Re: MySQL einzelne Daten ändern
Verfasst: Freitag 11. März 2011, 01:44
von Mathmos
Code: Alles auswählen
verbindung = MySQLdb.connect(host='***',port=***,user='***',passwd='***',db='***')
cursor3 = verbindung.cursor()
cursor3.execute("SELECT * FROM webs_forum_topics WHERE topicID = %s" %(topicID))
ergebnis3 = cursor3.fetchone()
ldate = time.time()
lposter = int_ergebnis_user
replys = ergebnis3[0][9] + 1
cursor3.execute("UPDATE webs_forum_topics SET lastdate=?, lastposter=?, replys=? WHERE topicID = ?", (ldate, lposter, replys, topicID))
so, habe ich es jetzt. aber leider haut das nicht nicht so ganz hin
Re: MySQL einzelne Daten ändern
Verfasst: Freitag 11. März 2011, 01:58
von deets
Das ist schade, aber was noch weniger hinhaut ist dir zu helfen, wenn du nicht preisgibst *was* genau nicht hinhaut.
Und den SQL-Injection-Fehler hast du immer noch drin.
Re: MySQL einzelne Daten ändern
Verfasst: Freitag 11. März 2011, 08:08
von /me
Was soll dieser Code eigentlich bewirken?
Ich habe den Verdacht, dass du eigentlich einfach replys (was besser korrekt
replies hieße) um 1 erhöhen möchtest. Dafür müsstest du allerdings nicht einmal ein SELECT durchführen.
Re: MySQL einzelne Daten ändern
Verfasst: Freitag 11. März 2011, 08:36
von sparrow
Vermeide "SELECT *" Abfragen aus Datenbanken.
Je nach Datenbank ist nämlich nicht definiert in welcher Reihenfolge die Felder in dem Tupel der Abfrage geordnet sind.
Ein Zugriff mit result[int] ist ab allem mit mehr als einem Feld Abfrage böse Magie und absolut nicht wartbar.
Ansonsten hat /me recht: Das Select-Statement ist überflüssig.
Re: MySQL einzelne Daten ändern
Verfasst: Freitag 11. März 2011, 09:08
von Mathmos
deets hat geschrieben:Das ist schade, aber was noch weniger hinhaut ist dir zu helfen, wenn du nicht preisgibst *was* genau nicht hinhaut.
Und den SQL-Injection-Fehler hast du immer noch drin.
Ich habe jetzt bei jeder Zeile ein try und except hinzugefügt. Und habe festgestellt, dass schon diese zeile nicht mehr hinhaut.
Code: Alles auswählen
cursor3.execute("SELECT * FROM webs_forum_topics WHERE topicID = ?", (topicID))
/me hat geschrieben:
Was soll dieser Code eigentlich bewirken?
Ich habe den Verdacht, dass du eigentlich einfach replys (was besser korrekt
replies hieße) um 1 erhöhen möchtest. Dafür müsstest du allerdings nicht einmal ein SELECT durchführen.
Ja, das möchte ich. Aber dazu möchte ich auch, wie oben genannt, noch 2 weitere Einträge ändern.
Habe jetzt diese Zeile mal ausprobiert. (ebenfalls mit try und except) Funktionoert leider auch nicht.
Code: Alles auswählen
cursor3.execute('update webs_forum_topics set replys=replys+? where topicID=?', (1, 'topicID'))
sparrow hat geschrieben:Vermeide "SELECT *" Abfragen aus Datenbanken.
Je nach Datenbank ist nämlich nicht definiert in welcher Reihenfolge die Felder in dem Tupel der Abfrage geordnet sind.
Ein Zugriff mit result[int] ist ab allem mit mehr als einem Feld Abfrage böse Magie und absolut nicht wartbar.
Ansonsten hat /me recht: Das Select-Statement ist überflüssig.
Ich habe das bisher immer so gemacht. Und bei der Datenbank, die ich verwende gab es auch noch nie Probleme damit =)
EDIT:
Ich bin eben auf `except Exception, e:` gestoßen und habe das gleich mal ausprobiert.
Die Fehlermeldung die ich bekommen lautet:
"not all arguments converted during string formatting"
Allerdings kann ich damit irgendwie nicht so recht was anfangen
Re: MySQL einzelne Daten ändern
Verfasst: Freitag 11. März 2011, 09:58
von sparrow
Mathmos hat geschrieben:Ich habe das bisher immer so gemacht. Und bei der Datenbank, die ich verwende gab es auch noch nie Probleme damit =)
Komm, wir gehen jetzt mal das Problem richtig an.
Was willst du eigentlich machen? Wie gesagt: das SELECT-Statement ist mit 95% Wahrscheinlichkeit überflüssig.
Code: Alles auswählen
import sqlite3
with sqlite3.connect(':memory:') as con:
cur = con.cursor()
cur.execute("CREATE TABLE webs_forum_topics " \
"(replys INTEGER, topicID INTEGER)")
cur.execute("INSERT INTO webs_forum_topics (replys, topicID) " \
"VALUES (?, ?)", (5, 1))
cur.execute("INSERT INTO webs_forum_topics (replys, topicID) " \
"VALUES (?, ?)", (8, 2))
cur.execute("INSERT INTO webs_forum_topics (replys, topicID) " \
"VALUES (?, ?)", (11, 3))
print cur.execute("SELECT * FROM webs_forum_topics").fetchall()
cur.execute("UPDATE webs_forum_topics SET replys = replys + 1 " \
"WHERE topicID = ?", (2,))
print cur.execute("SELECT * FROM webs_forum_topics").fetchall()
cur.close()
Re: MySQL einzelne Daten ändern
Verfasst: Freitag 11. März 2011, 10:14
von BlackJack
@Mathmos: Schau Dir doch die Ausnahmen mal an, die sagen ja nicht nur "irgendwas ist falsch", sondern haben in der Regel auch einen Typ und eine Nachricht, die einem verraten sollen was zu der Ausnahme geführt hat. Und es gibt auch einen Traceback der die betroffenen Programmzeilen auflistet -- man muss also nicht ein ``try``/``except`` um jede einzelne Zeile setzen um die problematische zu finden. Eigentlich sollte man gar kein ``try``/``except`` dafür setzen müssen und die Ausnahme einfach bis auf die oberste Ebene "wandern" lassen -- dann wird sie ja automatisch ausgegeben.
Das zweite Argument von `Cursor.execute()` sollte ein Tupel mit den Werten sein. Wenn es nur ein Wert ist, braucht man trotzdem ein Tupel mit eben diesem einen Wert darin. Ausserdem ist der Platzhalter für `MySQLdb` '%s' und nicht '?'.
Verbesserungsvorschläge, die dazu noch Code betreffen der nicht robust ist, mit einem "das habe ich schon immer so gemacht" abzubügeln, kommt übrigens nicht bei allen gut an.
Re: MySQL einzelne Daten ändern
Verfasst: Freitag 11. März 2011, 10:26
von deets
Also, ich hab' mal nen kleines script gebaut, dass dein Problem in sqlite loest.
Code: Alles auswählen
from sqlite3 import *
print "paramstyle:", paramstyle
conn = connect('/tmp/example.db')
c = conn.cursor()
c.execute("select count(*) from sqlite_master WHERE name=?", ("webs_forum_topics",))
table_exists = c.next()[0]
if not table_exists:
c.execute("""create table webs_forum_topics (
topicID int,
replys int,
lastpost int)""")
c.execute("""insert into webs_forum_topics values (?, ?, ?)""",
(1, 0, 1))
conn.commit()
topicID = 1
c.execute("""update webs_forum_topics set replys = replys + ? where topicID = ?""",
(1, topicID))
c.execute("""select * from webs_forum_topics where topicID = ? """, (topicID,))
for row in c:
print row
conn.commit()
*ACHTUNG*: der paramstyle deiner DB ist wichtig, wenn der nicht "qmark" ist, muessen statt Fragezeichen was anderes in die Statements!
Ausserdem verstehe ich das ganze try/except-gedoens nicht, wenn du gar nix machst, sollten die exceptions doch fliegen?!? dann kannst du auch sehen, was passiert...
Re: MySQL einzelne Daten ändern
Verfasst: Freitag 11. März 2011, 11:05
von Mathmos
Erstmal Danke
Es funktioniert jetzt. Ich habe nun solange rumprobiert bis es funktioniert hat =)
naja, ich habe nicht mit IDLE gearbeitet, da IDLE immer ne Fehlermeldung raushaut wenn man ein Icon setzt

aber ich werds mal wieder mit IDLE versuche.
@BlackJack und deets: Ja diese bösesn Fragezeichen haben bei mir nicht so ganz hingehauen
@sparrow und deets: Funktioniert leider bei mir nicht, ich benutze Python 2.5
@BlackJack: Ich habe die Vorschläge nicht abgebügelt. Ich wollte lediglich darauf hinweisen, dass mir bisher niemand gesagt hat, dass es scheiße ist, so wie ich das mache

Siehe hier:
http://www.python-forum.de/viewtopic.php?f=1&t=23773
Mein Code sieht nun so aus.
Gibts daran noch was zu verbessern?
Code: Alles auswählen
cursor3 = verbindung.cursor()
ldate = time.time()
lposter = int_ergebnis_user
cursor3.execute('UPDATE webs_forum_topics set lastdate=%d, lastposter=%d, replys=replys+%d where topicID=%d'% (ldate, lposter, 1, topicID))
Re: MySQL einzelne Daten ändern
Verfasst: Freitag 11. März 2011, 11:22
von BlackJack
@Mathmos: Du benutzt schon wieder ``%`` um die Werte in die SQL-Anfrage zu formatieren und nicht das zweite Argument von `execute()`.
Re: MySQL einzelne Daten ändern
Verfasst: Freitag 11. März 2011, 11:52
von Mathmos
ja, das ist auch irgendwie das einzige was geht.
Code: Alles auswählen
1. cursor3.execute('UPDATE webs_forum_topics set lastdate=%d, lastposter=%d, replys=replys+%d where topicID=%d', (ldate, lposter, 1, topicID))
2. cursor3.execute('UPDATE webs_forum_topics set lastdate=?, lastposter=?, replys=replys+? where topicID=?', (ldate, lposter, 1, topicID))
1.
Code: Alles auswählen
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python25\lib\lib-tk\Tkinter.py", line 1403, in __call__
return self.func(*args)
File "C:\Python25\xXBeispeileXx\GTS-VideoUpper.py", line 338, in UploadPics
cursor3.execute('UPDATE webs_forum_topics set lastdate=%d, lastposter=%d, replys=replys+%d where topicID=%d', (ldate, lposter, 1, topicID))
File "C:\Python25\lib\site-packages\MySQLdb\cursors.py", line 151, in execute
query = query % db.literal(args)
TypeError: int argument required
2.
Code: Alles auswählen
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python25\lib\lib-tk\Tkinter.py", line 1403, in __call__
return self.func(*args)
File "C:\Python25\xXBeispeileXx\GTS-VideoUpper.py", line 338, in UploadPics
cursor3.execute('UPDATE webs_forum_topics set lastdate=?, lastposter=?, replys=replys+? where topicID=?', (ldate, lposter, 1, topicID))
File "C:\Python25\lib\site-packages\MySQLdb\cursors.py", line 151, in execute
query = query % db.literal(args)
TypeError: not all arguments converted during string formatting
Re: MySQL einzelne Daten ändern
Verfasst: Freitag 11. März 2011, 12:01
von deets
Woher kommen denn die "%d"? Die sind Unfug. Ich habe kein MySQLdb zur Verfuegung, darum kann ich das nicht ueberpruefen. Aber IMHO ist das "%s", egal, was man fuer einen Wert reintut.
Und "geht nicht, ich habe Python2.5" ist keine Antwort auf etwas, dass ich geschrieben habe - denn alles, was ich dir gezeigt habe, habe ich mit Python2.5 gemacht.
Re: MySQL einzelne Daten ändern
Verfasst: Freitag 11. März 2011, 12:02
von BlackJack
@Mathmos: Der Platzhalter bei `MySQLdb` ist ja auch '%s' und nicht '%d' oder '?'. Das hatten wir aber schon mal…
Re: MySQL einzelne Daten ändern
Verfasst: Freitag 11. März 2011, 12:13
von Mathmos
args... das kommt davon wenn man C mit python vermischt^^
naja jetzt funktioniert =)
@ deets: also in IDLE bekomme ich dann immer folgende Meldung
Warning: 'with' will become a reserved keyword in Python 2.6
Re: MySQL einzelne Daten ändern
Verfasst: Freitag 11. März 2011, 12:40
von deets
Oh, es gibt %d auch in Python - aber nicht an dieser Stelle.
Und was das with angeht - das geht auch in Python2.5, dazu muss man
an den Anfang der Datei schreiben.
Re: MySQL einzelne Daten ändern
Verfasst: Freitag 11. März 2011, 12:43
von Mathmos
ah, ok
scheint nun zu funktionieren =)
Danke