variablen in sqlite schreiben

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
paranoidpenguin
User
Beiträge: 7
Registriert: Mittwoch 15. Juli 2009, 12:56

Hallo,

ich fange gerade an mich ein wenig mit Python zu beschäftigen und möchte nun diverse Variablen, die ich über die Eingabe ermittelt habe in eine Datenbank schreiben.

Leider funktioniert das nicht so, wie ich es gerne hätte

Code: Alles auswählen

def eingabe():
	datum = input("Datum: ")
	nummer = input("Nummer: ")
        name = input("Name: ")

connection = sqlite3.connect("datenbank.db")
cursor = connection.cursor()

eingabe()

sql= "INSERT INTO rollen VALUES (%s, %s, %s)"
        (datum, nummer, name)

print(sql)

cursor.execute(sql)
connection.commit()

connection.close()
                   
Kann mir da jemand helfen?

Danke
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo,

das hat mehrere Uhrsachen:
- Hast du die Tabelle vorher erzeugt? Das wird in deinem Code nicht klar.
- Dein Statement wird falsch zusammengesetzt. Es fehlen zum Beispiel die Anführungszeichen um die Werte. Das sollte man aber am "print" sehen. Übergebe das Tupel besser der execute-Methode und setze die Anfragen nicht per Hand zusammen. Gerade bei Benutzereingaben kann das sonst tödliche Folgen haben.

Für deine nächste Frage solltest du daran denken *was* nicht funktioniert. "Funktioniert nicht" ist eine äußerst dürftige Fehlerbeschreibung.
Das Leben ist wie ein Tennisball.
paranoidpenguin
User
Beiträge: 7
Registriert: Mittwoch 15. Juli 2009, 12:56

danke für die schnelle Antwort.

Ja, die Tabelle hatte ich vorher erzeugt. Hab nur nicht alles gepostet, weil ich dachte das wäre sonst zu unübersichtlich...

Hab das mal soweit geändert, das es funktioniert und was ausgibt.

Nun hätte ich gerne anstatt der "dt" Variablen ein richtiges Datum eingegeben. Welches Format muss ich da benutzen?
Zum anderen würde ich gerne die "material" Variable aus einem anderen Tupel übernehmen.
Wie mach ich das richtig?

Ist das jetzt so richtig mit execute? Oder geht das noch schlichter?

Code: Alles auswählen

#! /usr/bin/python

import sqlite3

connection = sqlite3.connect("material.db")
cursor = connection.cursor()

try:
	sql =	"CREATE TABLE rollen(" \
		"dt INTEGER," \
		"nummer INTEGER PRIMARY KEY, " \
		"se INTEGER, " \
		"rein INTEGER, " \
		"material INTEGER, " \
		"mag TEXT, " \
		"raus INTEGER, " \
		"rest INTEGER)"
	cursor.execute(sql)
except:
	print("Datenbank geladen")

dt = input("Drehtag: ")
nummer = input("Rollennummer: ")
rein = input("Eingelegt: ")
if rein != 122:
	se = input("Shortend von: ")
	cursor.execute("SELECT material FROM rollen WHERE nummer = (%s)"
		%(se))
	for m in cursor:
		print("Material: ", m)
	material = m
	connection.commit()
else:
	se = 0	
	material = input("Material: ")

mag = input("Magazinnummer: ")
raus = input ("Ausgelegt: ")
rest = rein - raus
if rest != 0:
	print("Shortend mit: ",rest, "m")
	
cursor.execute("INSERT INTO rollen VALUES (%s, %s, %s, %s, %s, %s, %s, %s)" 
	%(dt, nummer, rein, se, material, mag, raus, rest))
connection.commit()

cursor.execute("SELECT * FROM rollen")
for i in cursor:
	print(i)
connection.commit()

cursor.execute("SELECT material, SUM(raus) FROM rollen GROUP BY material, dt")
for i in cursor:
	print(i)
connection.commit()

connection.close()
Hoffe das ist nun ein wenig präziser :oops:
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Schau dir mal das Thema vorher an... Selber Titel wie deiner. Vielleicht mal auf die Idee gekommen, das zu lesen?! Da findest du z.B. folgenden Link:
[wiki]Parametrisierte SQL-Queries[/wiki]

Nächstes Mal so langen Quelltext auslagern oder wenigstens als Python-Quelltext deklarieren...

Zu deinem dt:
Du kannst die Datentypen aus dem Modul ``datetime`` in sqlite nutzen, das geht so:
http://docs.python.org/library/sqlite3. ... converters
Benutzeravatar
lutz.horn
User
Beiträge: 205
Registriert: Dienstag 8. November 2005, 12:57
Wohnort: Pforzheim

paranoidpenguin hat geschrieben:Nun hätte ich gerne anstatt der "dt" Variablen ein richtiges Datum eingegeben.

Code: Alles auswählen

from datetime import datetime
dt = datetime.strptime(raw_input("Drehtag: ", "%d.%m.%Y"))
http://docs.python.org/library/datetime.html
https://www.xing.com/go/invite/18513630.6a91d4
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Oh, dass es am Input auch schon hängt, hab ich mir gar nicht überlegt.
Wenn, dann aber so:

Code: Alles auswählen

from datetime import datetime
dt = datetime.strptime(raw_input("Drehtag: "), "%d.%m.%Y")
(Klammer falsch gesetzt)
Benutzeravatar
lutz.horn
User
Beiträge: 205
Registriert: Dienstag 8. November 2005, 12:57
Wohnort: Pforzheim

ice2k3 hat geschrieben:(Klammer falsch gesetzt)
Stimmt, danke.

Mir ist im Code des OP aufgefallen, dass immer "input" verwendet wird, das ja implizit "eval" aufruft. Das erscheit mir nicht sinnvoll. Deswegen würde ich immer "raw_input" verwenden und das Ergebnis auf den gewünschten Typ umwandeln. Beispiel:

Code: Alles auswählen

zahl = int(raw_input("Zahl: "))
SQLite ist ja ziemlich nachsichtig, was Datentype angeht. Gerade bei einem Datum würde ich mich aber nicht auf die rohe Eingabe des Benutzers verlassen sondern explizit mit "datetime.strptime()" umwandeln. Für andere Benutzereingaben gilt entsprechendes.
https://www.xing.com/go/invite/18513630.6a91d4
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

lutz.horn hat geschrieben:Mir ist im Code des OP aufgefallen, dass immer "input" verwendet wird, das ja implizit "eval" aufruft.
Es kann aber auch sein, dass der OP Python 3 nutzt, was die Klammern beim ``print`` andeuten, dann ist ``input`` okay.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
paranoidpenguin
User
Beiträge: 7
Registriert: Mittwoch 15. Juli 2009, 12:56

Vielen Dank für die Hilfe,
ich stell mich vielleicht wirklich etwas blöd an...

Das mit dem Datum hat geklappt, nur versteh ich immer noch nicht, warum es mir immer diesen Syntaxfehler gibt, wenn ich einen Wert aus einem anderen Tupel übernehmen will.
Ich hab das andere Thema gelesen, ich versteh es trotzdem nicht.

Achso: ja, Python 3.
Hab ich so aus dem Buch mit dem "input"
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Zum Thema Variablen in die Statements:
Du solltest die Statements nicht über die Stringformatierung zusammenbauen. Stattdessen kannst du in dein Statement sog. Platzhalter einbauen, bei sqlite sind das ``?``
Als zweites Argument beim Ausführen des Statements übergibts du dann die entsprechenden Variablen.

Bsp.

Code: Alles auswählen

sql = 'select * from table where id=? and value>?'
args = (id, value)
cursor.execute(sql, args)

# Beachte bei nur einer Variable:
sql = 'select * from table where id=?'
args = (id,) # Der 2. Parameter mit 1 Variablen muss so aussehen
cursor.execute(sql, args)
Zu deinem Fehler, an welcher Stelle tritt der Syntaxfehler auf?
paranoidpenguin
User
Beiträge: 7
Registriert: Mittwoch 15. Juli 2009, 12:56

Ich hab in Z.26 eine if-Anweisung, wo ich möchte, dass falls "rein" nicht 122 ist, die "material" Variable von der angegeben Rolle (se) für die neue Rolle übernommen wird.
Die if-Anweisung auch durchgeführt, aber "material" wird wegen einem Fehler nicht übernommen und die Rolle wird nicht in die Datenbank geschrieben.

Code: Alles auswählen

Traceback (most recent call last):
  File "./test.py", line 45, in <module>
    %(dt, nummer, rein, se, material, mag, raus, rest))
sqlite3.OperationalError: near ",": syntax error
Zu deinem Vorschlag mit dem Platzhalter:

Ich hab das jetzt so umgebaut

Code: Alles auswählen

sql = 'INSERT INTO rollen VALUES (?, ?, ?, ?, ?, ?, ?, ?)'
args = (dt, nummer, rein, se, material, mag, raus, rest)
cursor.execute(sql, args)
connection.commit()
Was muss ich denn mit dem "id" machen?
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Vergiss das id, sollte nur eine Beispielvariable sein.
Schlecht gewählt, weil das ein Python-Keyword ist ;)

Ja, so ist das richtig. Damit dürftest du auch keinen SQL-Syntaxfehler mehr bekommen?! Oder kommt immer noch dieser Fehler?
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

Commit() ist IMHO nur sinnvoll, wenn Änderungen an der Datenbank gemacht werden, nicht aber bei einer reinen Abfrage, oder?
paranoidpenguin
User
Beiträge: 7
Registriert: Mittwoch 15. Juli 2009, 12:56

Es kommt jetzt ein anderer Fehler.

Code: Alles auswählen

Traceback (most recent call last):
  File "./test.py", line 51, in <module>
    cursor.execute(sql, args)
sqlite3.InterfaceError: Error binding parameter 4 - probably unsupported type.
:cry:

Aber halt nur wenn ich über die if-Anweisung den Wert abfragen und übernehmen will.
Ich habs auch schon ohne commit versucht, hat allerdings keinen Unterschied gemacht.
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

imput() liefert einen String zurück, die Tabelle erwartet einen Integer.

Code: Alles auswählen

int(material)
könnte helfen.
paranoidpenguin
User
Beiträge: 7
Registriert: Mittwoch 15. Juli 2009, 12:56

Geht leider auch nicht

Code: Alles auswählen

TypeError: int() argument must be a string or a number, not 'tuple'
Mist...
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Zeile 30:

Code: Alles auswählen

for m, in cursor: 
        print("Material: ", m) 
    material = m 
Das Komma rein, dann passts.
paranoidpenguin
User
Beiträge: 7
Registriert: Mittwoch 15. Juli 2009, 12:56

Juhuu.

Danke, danke, danke.

Es funktioniert.
Was so ein Komma alles ausmachen kann....
Antworten