Achten Sie auf die Verwendung der Zeichenfolgeninterpolation für SQL-Abfragen, da die Eingabeparameter nicht korrekt ausgeblendet werden und Ihre Anwendung für SQL-Injection-Schwachstellen offen bleibt. Der Unterschied mag trivial erscheinen, aber in Wirklichkeit ist er riesig .
Falsch (mit Sicherheitsproblemen)
c.execute("SELECT * FROM foo WHERE bar = %s AND baz = %s" % (param1, param2))
Richtig (mit Flucht)
c.execute("SELECT * FROM foo WHERE bar = %s AND baz = %s", (param1, param2))
Dies trägt zur Verwirrung bei, dass die zum Binden von Parametern in einer SQL-Anweisung verwendeten Modifikatoren zwischen verschiedenen DB-API-Implementierungen variieren und dass die MySQL-Clientbibliothek die Stilsyntax printf
anstelle des allgemein akzeptierten '?' Marker (verwendet von zB python-sqlite
).
printf
Stil%s
Marker, und ich war sorta Angst , dass ich verwundbar Abfragen schrieb. Vielen Dank, dass Sie diese Sorgen ausgeräumt haben! :)c.execute("SELECT * FROM foo WHERE bar = %s", (param1,))
Sie haben einige Optionen zur Verfügung. Sie sollten sich mit der String-Iterpolation von Python vertraut machen. Nach diesem Begriff könnten Sie in Zukunft erfolgreicher suchen, wenn Sie solche Dinge wissen möchten.
Besser für Fragen:
some_dictionary_with_the_data = { 'name': 'awesome song', 'artist': 'some band', etc... } cursor.execute (""" INSERT INTO Songs (SongName, SongArtist, SongAlbum, SongGenre, SongLength, SongLocation) VALUES (%(name)s, %(artist)s, %(album)s, %(genre)s, %(length)s, %(location)s) """, some_dictionary_with_the_data)
Da Sie wahrscheinlich bereits alle Ihre Daten in einem Objekt oder Wörterbuch haben, passt das zweite Format besser zu Ihnen. Es ist auch schade, "% s" -Auftritte in einer Zeichenfolge zählen zu müssen, wenn Sie zurückkommen und diese Methode in einem Jahr aktualisieren müssen :)
quelle
Die verknüpften Dokumente geben das folgende Beispiel:
cursor.execute (""" UPDATE animal SET name = %s WHERE name = %s """, ("snake", "turtle")) print "Number of rows updated: %d" % cursor.rowcount
Sie müssen dies also nur an Ihren eigenen Code anpassen - Beispiel:
cursor.execute (""" INSERT INTO Songs (SongName, SongArtist, SongAlbum, SongGenre, SongLength, SongLocation) VALUES (%s, %s, %s, %s, %s, %s) """, (var1, var2, var3, var4, var5, var6))
(Wenn SongLength numerisch ist, müssen Sie möglicherweise% d anstelle von% s verwenden.)
quelle
%s
dort verwenden, egal welcher Typ. @ Sheki: JaSelbst wenn Ihre Variable (SongLength) numerisch ist, müssen Sie sie mit% s formatieren, um den Parameter korrekt zu binden. Wenn Sie versuchen,% d zu verwenden, wird eine Fehlermeldung angezeigt. Hier ist ein kleiner Auszug aus diesem Link http://mysql-python.sourceforge.net/MySQLdb.html :
Um eine Abfrage auszuführen, benötigen Sie zuerst einen Cursor, und dann können Sie Abfragen darauf ausführen:
c=db.cursor() max_price=5 c.execute("""SELECT spam, eggs, sausage FROM breakfast WHERE price < %s""", (max_price,))
In diesem Beispiel ist max_price = 5 Warum wird dann% s in der Zeichenfolge verwendet? Weil MySQLdb es in einen SQL-Literalwert konvertiert, der die Zeichenfolge '5' ist. Wenn es fertig ist, sagt die Abfrage tatsächlich "... WHERE Preis <5".
quelle
Als Alternative zur gewählten Antwort und mit der gleichen sicheren Semantik wie bei Marcel gibt es hier eine kompakte Möglichkeit, die Werte mithilfe eines Python-Wörterbuchs anzugeben. Es hat den Vorteil, dass es einfach geändert werden kann, wenn Sie Spalten zum Einfügen hinzufügen oder entfernen:
meta_cols=('SongName','SongArtist','SongAlbum','SongGenre') insert='insert into Songs ({0}) values ({1})'. .format(','.join(meta_cols), ','.join( ['%s']*len(meta_cols) )) args = [ meta[i] for i in meta_cols ] cursor=db.cursor() cursor.execute(insert,args) db.commit()
Wobei meta das Wörterbuch ist, das die einzufügenden Werte enthält. Das Update kann auf folgende Weise erfolgen:
meta_cols=('SongName','SongArtist','SongAlbum','SongGenre') update='update Songs set {0} where id=%s'. .format(','.join([ '{0}=%s'.format(c) for c in meta_cols ])) args = [ meta[i] for i in meta_cols ] args.append( songid ) cursor=db.cursor() cursor.execute(update,args) db.commit()
quelle
Die erste Lösung funktioniert gut. Ich möchte hier ein kleines Detail hinzufügen. Stellen Sie sicher, dass die Variable, die Sie ersetzen / aktualisieren möchten, vom Typ str sein muss. Mein MySQL-Typ ist dezimal, aber ich musste die Parametervariable als str festlegen, um die Abfrage ausführen zu können.
temp = "100" myCursor.execute("UPDATE testDB.UPS SET netAmount = %s WHERE auditSysNum = '42452'",(temp,)) myCursor.execute(var)
quelle
Hier ist eine andere Möglichkeit, dies zu tun. Es ist auf der offiziellen MySQL-Website dokumentiert. https://dev.mysql.com/doc/connector-python/de/connector-python-api-mysqlcursor-execute.html
Im Geiste verwendet es die gleiche Mechanik wie die Antwort von @Trey Stout. Ich finde dies jedoch schöner und lesbarer.
insert_stmt = ( "INSERT INTO employees (emp_no, first_name, last_name, hire_date) " "VALUES (%s, %s, %s, %s)" ) data = (2, 'Jane', 'Doe', datetime.date(2012, 3, 23)) cursor.execute(insert_stmt, data)
Und um den Bedarf an Variablen besser zu veranschaulichen:
NB: Beachten Sie die Flucht.
employee_id = 2 first_name = "Jane" last_name = "Doe" insert_stmt = ( "INSERT INTO employees (emp_no, first_name, last_name, hire_date) " "VALUES (%s, %s, %s, %s)" ) data = (employee_id, conn.escape_string(first_name), conn.escape_string(last_name), datetime.date(2012, 3, 23)) cursor.execute(insert_stmt, data)
quelle