Daten von Variablen in postgreSQL Datenbank schreiben

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
sunnyraven
User
Beiträge: 17
Registriert: Montag 10. Juni 2013, 13:30

Ich steh mal wieder auf dem Schlauch. Ich lese Daten ein und habe diese dann als Variabeln. Diese Variabeln möchte ich dann in ein postgreSQL Datenbank schreiben. Das war mein Plan:

Code: Alles auswählen

        conn = psycopg2.connect(database="reader", user="xxx", password="123")
        curs = conn.cursor()
        sql="""INSERT INTO devices (t_stamp, device_id, device_type, u_dc, i_dc) VALUES (%s, %s, %s, %s, %s, %s, %s)"""
        curs.execute(sql, (dv_timestamp, device_id, DEVICE_TYPE))
        conn.commit()
        curs.close()
        conn.close() 
Mit solch einem Code bekomme ich die Fehlermeldung:

psycopg2.ProgrammingError: FEHLER: Syntaxfehler bei »2013

Die Deklaration in der Datenbank sieht so aus:
t_stamp ist vom Type "timestamp"
device_id und device_type sind "character varying"
u_dc und i_dc sind "numeric"

Kann mir jemand von Euch sagen was ich falsch mache, kennt jemand einen Beitrag mit einem Ähnlichen problem welchen ich zu Rate ziehen kann, oder kennt wer eine Seite im Netz wo ich die nötigen Infos herbekomme.

Vielleicht fehlt mir auch nur der richtige Suchbegriff.

Leider lassen sich die Bücher welche ich zum Thema Python habe nicht so richtig über postgreSQL aus.

Vielen Dank für die Hilfe
Zuletzt geändert von Anonymous am Montag 17. Juni 2013, 14:38, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
BlackJack

@sunnyraven: Zähle mal bitte die Spaltennamen in der SQL-Anweisung, dann die Anzahl der Platzhalter für Werte in der SQL-Anweisung, und dann bitte die Anzahl der Werte die bei `execute()` an diese SQL-Anweisung übergeben werden.
sunnyraven
User
Beiträge: 17
Registriert: Montag 10. Juni 2013, 13:30

Sorry, das war mein Fehler denn ich habe den Code gekürzt denn es sind am Ende über 30 Werte welche übergeben werden.
Das gibt aber auch eine andere Fehlermeldung.

So sollte es passen:

Code: Alles auswählen

 conn = psycopg2.connect(database="reader", user="xxx", password="123")
        curs = conn.cursor()
        sql="""INSERT INTO devices (t_stamp, device_id, device_type, u_dc, i_dc) VALUES (%s, %s, %s, %s, %s)"""
        curs.execute(sql, (dv_timestamp, device_id, DEVICE_TYPE, U_DC, I_DC))
        conn.commit()
        curs.close()
        conn.close()
 
Was mir noch nicht so ganz klar ist, ist die Sache mit dem "%s" an anderer Stelle habe ich da schon "?" gesehen. Ich finde aber auch keine Erklärung dafür im Netz oder Bücher
BlackJack

Für die Platzhalter gibt es verschiedene Möglichkeiten: http://www.python.org/dev/peps/pep-0249/#paramstyle

Über dieses Attribut wird leider nur ein Name zurückgegeben, auch wenn das Modul mehrere Alternativen unterstützt. Das Fragezeichen und „named” sind SQL-Standard.

Was für Werte/Typen übergibst Du denn?
sunnyraven
User
Beiträge: 17
Registriert: Montag 10. Juni 2013, 13:30

Vielen Dank für die schnelle Reaktion, trotz der Hitze:

Die Deklaration in der Datenbank sieht so aus:
t_stamp ist vom Type "timestamp"
device_id und device_type sind "character varying"
u_dc und i_dc sind "numeric"
BlackJack

@sunnyraven: Ich meinte die Wert/Typen auf Python-Seite, die die Probleme verursachen.
sunnyraven
User
Beiträge: 17
Registriert: Montag 10. Juni 2013, 13:30

Hallo BlackJack
Die Daten lese ich aus einer XML Datei und sie sehen so aus:

t_stamp: 2013-06-17 19:44:00 <class 'str'>
device_id: a9cee487ab2dd2341ddc3860c0a6553d <class 'str'>
device_type: text <class 'str'>
u_dc: 386 <class 'int'> interpretiert
i_dc: 0.758 <class 'int'> interpretiert


Eine direkte Deklaration habe ich noch nicht vorgenommen!?
BlackJack

@sunnyraven: In Python deklariert man keine Typen. Die Werte haben aber Typen und die müssen zu den Typen in der Datenbank passen. Um noch mal die Beschreibung der DB API 2.0 zu verlinken: http://www.python.org/dev/peps/pep-0249 ... nstructors

Du müsstest Deinen Zeitstempel also in ein entsprechendes `Timestamp`-Objekt umwandeln.
Drache
User
Beiträge: 51
Registriert: Montag 29. November 2010, 21:51
Wohnort: Berlin
Kontaktdaten:

schau mal ob dir das dir weiter hilft:
sql="""INSERT INTO "devices" ("t_stamp", "device_id", "device_type", "u_dc", "i_dc") VALUES ('%s', %s, '%s', '%s', '%s')"""
oder print(sql)
und in pgadmin3 den sql string mit copy und paste einfügen und ausführen, um eine bessere Fehlermeldung zu bekommen.

Drache
BlackJack

@Drache: Die " sind mindestens überflüssig und die ' sind schlicht falsch.
Drache
User
Beiträge: 51
Registriert: Montag 29. November 2010, 21:51
Wohnort: Berlin
Kontaktdaten:

@BlackJack
so funktioniert es bei mir.
bin über dein 'falsch' und "überflüssig" irritiert.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Drache hat geschrieben: bin über dein 'falsch' und "überflüssig" irritiert.
Überflüssig, weil man vernünftige Namen nicht escapen muss (Bei Tabellen-Namen nur aus Ziffern bestehend braucht das meiner Erfahrung nach dann jeder SQL-Dialekt - aber wer macht das auch schon?), falsch, weil die ``execute``-Methode des Cursor-Objektes selber weiß, für welches Zielfeld sie String-Literale generieren muss. Im Falle eines numerischen Wertes würdest Du vermutlich einen Fehler bekommen.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

@Drache: Die ' sind falsch wenn man `execute()` richtig verwendet. Um die Platzhalter gehört nichts was „escaped”, denn das macht das Datenbankmodul schon für Dich. Und das sollte man in aller Regel auch das DB-Modul machen lassen. Stichwort „SQL-Injection”. Du wirst wahrscheinlich Zeichenkettenformatierung verwenden und Dir damit eine schöne Sicherheitslücke in Dein Programm reissen.

Und die " sind halt überflüssig solange in den Namen nicht irgend etwas besonderes ist.
Drache
User
Beiträge: 51
Registriert: Montag 29. November 2010, 21:51
Wohnort: Berlin
Kontaktdaten:

@BlackJack @Hyperion,

könnt ihr mir mal ein minimal Beispiel zeigen,
am besten wo in einem String ein , vorkommt ?
Wäre euch sehr dankbar.
BlackJack

@Drache: Ungetestet:

Code: Alles auswählen

    cursor.execute('INSERT INTO table_name (column_name) VALUES (%s)', ('Zeichenkette, mit Komma',))
Und das Unterscheidet sich überhaupt nicht von einem Beispiel ohne Komma oder mit jedem beliebigen anderen Zeichen. Genau darum lässt man so etwas ja auch das DB-Modul machen.
sunnyraven
User
Beiträge: 17
Registriert: Montag 10. Juni 2013, 13:30

Vielen, vielen Dank für die Hilfe soory für die verspätete Antwort ich hatte diese aus Versehen in einem falschen Beitrag geschrieben.

das Problem lag darin, dass an einigen Stellen aus dem XML, lesen werte so: zurück kamen. Diese Werte habe ich nun durch eine Null ersetzt und schon gehts.

Dank Eurer Diskussion zum Thema habe ich wieder einiges dazugelernt.
Antworten