Variabel um 1 erhöhen

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
nurmili
User
Beiträge: 6
Registriert: Sonntag 16. August 2015, 08:03

Hallo Leute,
ich bin an einer Zugangskontrolle und lese Über ein Lesegerät einen Transponder aus und kontrliere in meiner Datenbank "nutzer.db"
ob der Textfeil aus dem Transponder vorhanden ist !
Das mache ich so:

Code: Alles auswählen

def DatenAbfrage():
	
	con = sqlite3.connect("nutzer.db")
	dbcursor = con.cursor()
	ke = input() # Liest den Chip ein
	dbcursor.execute('SELECT * FROM fueller WHERE kennung=?', (ke,))
	a = (dbcursor.fetchone())
	if a == None:
		ZugangVerweigert()		
	else:
		ZugangErlaubt()
	con.close()
Das funtioniert auch alles !
Jetzt möchte ich aber die Variabel der Spalte in der Tabelle "anzahl_f" um 1 erhöhen, natürlich nur bei dem, wo ich vorher die
berechtigung , siehe oben geprüft habe !

Nochmal auf Deutsch, jedesmal nach einem berechtigten Zugriff soll sich Variable in "anzahl_f" um 1 erhöhen !

Ich hoffe ich habe mich halbwegs verständlich ausgedrückt ?

Ich bin am verzweifeln !

Gruß nurmili
Zuletzt geändert von Anonymous am Montag 21. März 2016, 17:25, insgesamt 1-mal geändert.
Grund: Quelltext in Code-Tags gesetzt.
BlackJack

@nurmili: Dann müsstest Du am besten nicht alle Spalten von dem Datensatz abfragen, sondern nur den Wert, der Dich auch tatsächlich interessiert. Und wenn da etwas anderes als `None` geliefert wird, holst Du den Wert aus `a` (sehr schlechter Name!), erhöhst den um 1 und speicherst den zurück in die Datenbank. Oder Du erledigst das erhöhen gleich im SQL-Ausdruck.
bb1898
User
Beiträge: 200
Registriert: Mittwoch 12. Juli 2006, 14:28

BlackJack hat geschrieben:@nurmili: Dann müsstest Du am besten nicht alle Spalten von dem Datensatz abfragen, sondern nur den Wert, der Dich auch tatsächlich interessiert. Und wenn da etwas anderes als `None` geliefert wird, holst Du den Wert aus `a` (sehr schlechter Name!), erhöhst den um 1 und speicherst den zurück in die Datenbank. Oder Du erledigst das erhöhen gleich im SQL-Ausdruck.
Das Erhöhen gleich im SQL-Ausdruck (also direkt ein UPDATE statt SELECT) klingt gut, aber ich sehe ein Problem mit der nötigen Rückmeldung für "ZugangVerweigert()" bzw. "ZugangErlaubt()". Dafür braucht es cursor.rowcount und dazu sagt die Dokumentation (Python 3.4, das dürfte hier aber egal sein):
"Although the Cursor class of the sqlite3 module implements this attribute, the database engine’s own support for the determination of “rows affected”/”rows selected” is quirky."
BlackJack

@bb1898: Ich sehe da kein Problem. Man hat ja vorher geprüft ob die ID existiert.
bb1898
User
Beiträge: 200
Registriert: Mittwoch 12. Juli 2006, 14:28

BlackJack hat geschrieben:@bb1898: Ich sehe da kein Problem. Man hat ja vorher geprüft ob die ID existiert.
Ja, _wenn_ zuerst das SELECT ausgeführt wird. Dann habe ich Deinen Vorschlag, das Erhöhen gleich im SQL Ausdruck zu erledigen, vielleicht missverstanden: ich dachte, Du schlägst UPDATE statt SELECT vor und nicht erst SELECT und dann UPDATE. Klar, UPDATE würde nur ausgeführt, wenn die ID existiert. So weit, so gut. Aber, Frage an nurmili: müssen die Funktionen "ZugangVerweigert" und "ZugangErlaubt" nicht mehr tun als nur anzahl_f erhöhen? Mindestens mal melden, wie es mit dem Zugang aussieht? Oder gleich die Türe auf- bzw. zusperren?

Das Problem, das ich sehe, entsteht dadurch, dass sqlite anscheinend nicht zuverlässig zurückmeldet, wie viele Datensätze bei einem Update geändert wurden.
hans
User
Beiträge: 728
Registriert: Sonntag 22. September 2002, 08:32
Wohnort: Sauerland
Kontaktdaten:

bb1898 hat geschrieben:Das Problem, das ich sehe, entsteht dadurch, dass sqlite anscheinend nicht zuverlässig zurückmeldet, wie viele Datensätze bei einem Update geändert wurden.
Muss ich das in vorliegendem Fall wissen? Ich gehe einmal davon aus, das die Tabelle einen UNIQU INDEX für die Transponderkennung hat. Dann kann nur ein Datensatz geändert werden.

Es ist Schade dass SQLite keine UDF's kennt, wie z.b. Firebird. Ich würde in dem Fall so vorgehen, dass ich eine LOG-Tabelle in der Datenbank habe. Würde die Transponderkennung an die UDF übergeben, welche den LOG-File schreibt und auch entscheidet, ob Zugang erlaubt oder nicht erlaubt ist. Und diese(r) Wert(e) wird an den Aufruf zurückgegeben und arbeitet wesentlich effizienter, als das durch Einzelaufrufe aus einem Programm heraus mache.
BlackJack

@hans: Kenne mich mit Firebird nicht aus aber es gibt sqlite3.Connection.create_function(). Allerdings finde ich so etwas immer etwas unschön weil man sich damit an das DBMS bindet und nicht so leicht wechseln kann.
Benutzeravatar
miracle173
User
Beiträge: 127
Registriert: Samstag 6. Februar 2016, 00:28

Hallo @nurmili
nurmili hat geschrieben:die Variabel der Spalte in der Tabelle "anzahl_f"
Wie heisst die Tabelle, wie heißt die Spalte, die erhöht werden soll und wie finde ich die Zeilr der Tabelle, wo die Spale erhöht werden soll?

Die Erhöhung um 1 führt man mit einem Updatestatement durch.
Nehmen wir an die Spale, die erhöht werden soll heißt anzahl_f und ist ebenfalls in der Tabelle fuellung und die Kennung ist eindeutig in dieser Tabelle, dann wäre

Code: Alles auswählen

      dbcursor.execute('UPDATE fueller SET anzahl_f=anzahl_f+1 WHERE kennung=?', (ke,))
das geeignete Statement. Möglicherweise ist noch ein commit-Statement notwendig. Das hängt von der Datenbank und den Verbindungseinstellungen ab.


Ich würde eigentlich nicht versuchen, wie vorgeschlagen, das Überprüfen der Berechtigung (select statement) mit dem Registrieren des Zutritts (update statement) zu einem Datenbankstatement zu verbinden. Das sind zwei unabhängige Operationen. Zum Beispiel wäre es denkbar, dass die Funktion ZugangErlaubt noch eine Ausnahme erzeugt, weil das Terminal aus technischen Gründen keinen Zugriff ermöglichen kann.

Ich würde auch die Funktion DatenAbfrage anders definieren, nämlich

Code: Alles auswählen

def DatenAbfrage(ke):
und die Funktion input außerhalb der Funktion aufrufen. Dann kannst du die Funktion testen, ohne Terminaleingaben durchzuführen

Ebenso würde ich die Datenbankzugriffe in Funktionen kapseln. Das erleichter das Testen und die Portirbarkeit.

Schliesslich solltest du garantieren, dass die Datenbank-Verbindung auch wieder geschlossen wird. Das kannst du mit einem try Statement erreichen.

Du solltest die Datenmenge, die du von der Datenbank anforderst, immer so kliein wie möglich machen, also besser z. B.

Code: Alles auswählen

'SELECT 1 FROM fueller WHERE kennung=?'
Antworten