Seite 1 von 1
execute und Platzhalter
Verfasst: Montag 22. Juni 2009, 19:15
von start_with_python
Hallo!
Folgender Code treibt mich in den Wahnsinn:
Code: Alles auswählen
fields = data_dict.keys()
values = data_dict.values()
placeholder = "%s"
fieldlist = ",".join(fields)
placeholderlist = ",".join([placeholder] * len(fields))
query = "insert into 'Adressdaten' (%s) values (%s)" % (fieldlist, placeholderlist)
curser.execute(query, values) # Hier stört sich das Script
Fehler:
Code: Alles auswählen
curser.execute(query, values)
sqlite3.OperationalError: near "%": syntax error
Ich fasse kurz zusammen was ich mache: Ich hab ein Dictionary mit "Spaltenname":"DatenZumSpeichern". Der Schnipsel füllt dann das query mit den Spalten und der passenden Anzahl von Platzhaltern für die späteren Daten. Bis hierhin klappt alles, das haben meine Tests ergeben.
query ist wie gewollt ein String, values eine Liste.
Im execute sollte er mir aber nun die Platzhalter im query durch die Daten in den values ersetzen. Das mag er aber aus irgendeinem, mir nicht ersichtlichen Grund nicht.
Habt ihr eine Idee? Sehe ich den Wald vor lauter Bäumen nicht?
Verfasst: Montag 22. Juni 2009, 20:04
von Hyperion
Generell erst einmal:
[wiki]Parametrisierte SQL-Queries[/wiki]
Die Parameter bitte nicht so zusammenfrickeln, sondern besser einzeln übergeben.
Du willst imho mehere Inserts ausführen. Das solltest Du imho mit einer Schleife lösen.
Verfasst: Montag 22. Juni 2009, 21:59
von start_with_python
Hallo,
ja, das ganze läuft in einer Schleife. Ich muss mir angewöhnen und genauer zu beschreiben was ich vor habe
Also. Das soll im Endeffekt eine Funktion werden, die Daten aus einer CSV ausliest. In der ersten Zeile stehen die Namen der späteren Spalten inder Datenbank.
Der Funktion werden einige dieser Namen mitgegeben, daraus wurstet das Script dann eine Datenbank und soll sie füllen. Da die Anzahl und die Namen der Spalten flexibel sind, muss ich das so machen wie oben.
Im Endeffekt entspricht meine Version denen aus deinem Link, oder?
Verfasst: Dienstag 23. Juni 2009, 14:27
von Hyperion
start_with_python hat geschrieben:
ja, das ganze läuft in einer Schleife. Ich muss mir angewöhnen und genauer zu beschreiben was ich vor habe
Dann solltest Du die auch angeben
Der Funktion werden einige dieser Namen mitgegeben, daraus wurstet das Script dann eine Datenbank und soll sie füllen. Da die Anzahl und die Namen der Spalten flexibel sind, muss ich das so machen wie oben.
Du musst doch aber wissen, in welche Tabelle Du was schreibst. Also kannst Du das dann doch auch entsprechend mappen.
Im Endeffekt entspricht meine Version denen aus deinem Link, oder?
Hast Du Dir das auch durchgelesen? Schau es Dir noch mal genau an
Eine mögliche Alternative wäre für Dich auch executemany(). Damit sparst Du Dir die Schleife bei vielen gleichartigen insert-Statements. In der Python-Doku zu SQLite gibts da Beispiele.
Auf jeden Fall musst Du Dir im klaren sein, welche Struktur Deine Parameter haben müssen und welche sie tatsächlich haben. Das war nämlich der Hauptfehler auf Sprachebene in Deinem Snippet.
Verfasst: Dienstag 23. Juni 2009, 17:50
von start_with_python
Hyperion hat geschrieben:start_with_python hat geschrieben:
Im Endeffekt entspricht meine Version denen aus deinem Link, oder?
Hast Du Dir das auch durchgelesen? Schau es Dir noch mal genau an
Ja, finde ich doch. Hat doch große Ähnlichkeiten mit dem "format"-Beispiel, oder nicht?
Ich habe das Problem allerdings nun gelöst bekommen. Es lag ganz einfach an dem falschen "placeholder". Das darf bei SQL anscheinend nicht "%s", sondern muss ein "?" sein.
So klappt es also nun:
Code: Alles auswählen
fields = data_dict.keys()
values = data_dict.values()
placeholder = "?"
fieldlist = ",".join(fields)
placeholderlist = ",".join([placeholder] * len(fields))
query = "insert into 'Adressdaten' (%s) values (%s)" % (fieldlist, placeholderlist)
cursor.execute(query, values)
print "Erfolg!"
Verfasst: Mittwoch 24. Juni 2009, 09:29
von Hyperion
Wobei ich immer noch keine Schleife bei Dir sehe? An welcher Stelle iterierst Du denn nun über die Daten?
Verfasst: Mittwoch 24. Juni 2009, 13:49
von start_with_python
Der funktion wird eine Liste mit den Spaltennamen übergeben, die wir haben wollen (in der CSV-Datei gibt es noch mehr Spalten, die ich aber nicht haben will):
Code: Alles auswählen
column=["ANREDE", "NAME", "VORNAME", "LAND", "PLZZ", "ORT", "STRASSE", "TELEFON", "TELEFAX", "TELEFON2", "BEMERKUNG", "STICHWORT1", "STICHWORT2", "ZUSATZ1", "ZUSATZ2", "ERFDAT", "L_DAT", "RECORDID"]
So schaut es mit der Schleife aus:
Code: Alles auswählen
reader = csv.reader(open(data, "rb"), delimiter=";")
row_count = 0
column_check=[]
for row in reader:
#~ Die Erste Zeile enthaelt die SPaltennamen. Wir suchen die Nummern der Spalten
if row_count <= 0:
print "Spalten mit Vorgabe abgleichen..."
col_count = 0
for i in row:
if i in column:
column_check.append(col_count)
col_count += 1
if len(column_check) != len(column):
sys.exit("Fehler: Die Ausgangsdatei enthaelt nicht alle \
benoetigten Spalten! Programm wird beendet!")
#~ Jetzt die Eingabe der Datensaetze die benoetigt werden
else:
col_count = 0
col_index = 0
data_dict = {}
error_log = 0
#~ print "-----"
for i in row:
if col_count in column_check:
#~ print "%s ist da und bezeichnet %s" % (column[col_index], i)
data_dict[column[col_index]] = i.decode("utf-8")
col_index += 1
col_count += 1
try:
fields = data_dict.keys()
values = data_dict.values()
placeholder = "?"
fieldlist = ",".join(fields)
placeholderlist = ",".join([placeholder] * len(fields))
query = "insert into 'Adressdaten' (%s) values (%s)" % (fieldlist, placeholderlist)
cursor.execute(query, values)
#~ print "Speichere Datensatz", data_dict['VORNAME'], data_dict['NAME'], " - Erfolg!"
print ".",
sys.stdout.flush()
time.sleep(0.001)
except:
print "\nFehler beim Import von Datensatz: ", data_dict['VORNAME'], data_dict['NAME'], "\n"
error_log += 1
row_count += 1
print "\nCheck: ", column_check
connection.commit()
print " * Import beendet"
print " * Fehler: ", error_log
Funktioniert wunderbar
(Ich weiß, hält sich noch nicht an die PEP8. Nicht böse sein!)
Verfasst: Mittwoch 24. Juni 2009, 14:02
von lunar
Wofür "sys.stdout.flush()" und wofür "time.sleep()"?
Ferner solltest du den Commit einen finally-Block stellen, damit Daten auch korrekt geschrieben werden, wenn eine Ausnahme eintritt. Apropos Ausnahme: Wenn schon ein "except" ohne konkrete Ausnahme, dann wenigstens mit Ausgabe des Tracebacks! Eigentlich solltest du aber mindestens "Exception" angeben, denn so fängst du auch einen KeyboardInterrupt und einen SystemExit ab.
Verfasst: Mittwoch 24. Juni 2009, 14:17
von start_with_python
lunar hat geschrieben:
Wofür "sys.stdout.flush()" und wofür "time.sleep()"?
Überbleibsel. Ich mag es, wenn ich den Fortschritt "sehen" kann. Unnütz und verlangsamend, aber ich mags
lunar hat geschrieben:
Ferner solltest du den Commit einen finally-Block stellen, damit Daten auch korrekt geschrieben werden, wenn eine Ausnahme eintritt. Apropos Ausnahme: Wenn schon ein "except" ohne konkrete Ausnahme, dann wenigstens mit Ausgabe des Tracebacks! Eigentlich solltest du aber mindestens "Exception" angeben, denn so fängst du auch einen KeyboardInterrupt und einen SystemExit ab.
Ok, danke. Das werde ich mit einbauen.
lunar hat geschrieben:SystemExit
== sys.exit() ?
Oder auch aus anderen Gründen?
Verfasst: Mittwoch 24. Juni 2009, 14:19
von lunar
Ja, SystemExit wird durch sys.exit() ausgelöst.