MySQL Insert mit Dictionarys

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
audacity363
User
Beiträge: 83
Registriert: Dienstag 6. August 2013, 18:59

Guten Morgen,
ich habe ein Dictionary mit 11 Einträgen und dieses soll in eine MySQL Tabelle eingetragen werden. Dabei sind die Keys == Spaltenname. An sich ist es ja kein Problem:

Code: Alles auswählen

cursor.execute("insert into tabelle (zeilenname1, zeilenname2, usw) values (%s, %s, usw)", (dic["zeilenname1"], dic["zeilenname2"], usw))
Allerdings ist das ganze bei 11 Spalten eine verdammt lange Query und auch sehr Fehleranfällig, wenn man mal eine Spalte hinzufügt oder wegnimmt. Außerdem bin ich mir sicher, das es eine schönere Methode gibt.
Bei Google habe ich dann noch dies hier gefunden:

Code: Alles auswählen

qmarks = ','.join('?' * len(dic))
qry = "insert into tabelle (%s) values (%s)" % (qmarks, qmarks)
c.execute(qry, dic.keys() + dic.values())
Dort bekomme ich dann aber den TypeError:

Traceback (most recent call last):
File "function.py", line 34, in start
c.execute(qry, infos.keys() + infos.values())
File "/usr/lib/python2.7/dist-packages/MySQLdb/cursors.py", line 159, in execute
query = query % db.literal(args)
TypeError: not all arguments converted during string formatting
BlackJack

@audacity363: Die Platzhalter in SQL sind nur für *Werte* nicht für so Dinge wie Spaltennamen. Das ist also falsch was Du da ergooglet hast.

Finde heraus wie man bei der von Dir verwendeten Datenbank benannte Platzhalter für `execute()` angibt, und verwende die. SQL-Standard ist ``:name``, aber leider gibt es da ja genau wie beim ``?`` ein paar Variationen in der Python DB-API. Einer der Gründe warum ich gerne SQLAlchemy dazwischen schalte.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

audacity363 hat geschrieben: Allerdings ist das ganze bei 11 Spalten eine verdammt lange Query und auch sehr Fehleranfällig, wenn man mal eine Spalte hinzufügt oder wegnimmt.
Eigentlich *ist* es schon ein Fehler, wenn man "mal" Spalten hinzufügt oder wegnimmt. Ein (relationales!) DB-Design sollte schon ziemlich fix sein. Natürlich kann sich mal etwas ändern, aber das sollte natürlich nicht alle Tage passieren. Und falls doch, muss man den Code eh testen - egal, ob man nun an den Parametern etwas geändert hat.

Im übrigen könntest Du die Namen doch tatsächlich aus dem Dictionary generieren lassen:

Code: Alles auswählen

d = {"foo": "abc", "bar": 42}
", ".join(d.keys())
> 'foo, bar'

"INSERT INTO Table ({}) VALUES (...)".format(", ".join(d.keys()))

> 'INSERT INTO Table (foo, bar) VALUES (...)'
Über die Anzahl an Schlüssel kommst Du dann sogar auf die Einträge an Platzhaltern in der VALUES-Klausel:

Code: Alles auswählen

["%s"] * len(d.keys())
>['%s', '%s']
Dies kannst Du analog zu oben einbauen.

Last but not least bleiben die Werte... diese kannst Du doch einfach per ``*dict.keys()`` angeben :K
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
audacity363
User
Beiträge: 83
Registriert: Dienstag 6. August 2013, 18:59

@BlackJack
SQLAlchemy habe ich mir auch schon mal angeschaut, das ist aber schon ne ganze Weile her. "Damals" habe ich es nicht wirklich verstanden, da habe ich aber auch gerade erst mit Python angefangen vielleicht wird es auch mal wieder Zeit sich dies anzuschauen.

@Hyperion
Okey danke, denke aber werde mich dann doch erstmal wieder mit SQLAlchemy beschäftigen. Werde es trotzdem erst einmal versuchen, damit das Programm läuft.
Antworten