SQLite: Prüfen, ob eine Tabelle noch leer ist

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
mintpc
User
Beiträge: 50
Registriert: Montag 23. Januar 2012, 12:44

Hallo zusammen,

ich möchte prüfen, ob eine Tabelle noch leer ist, d.h. ob noch keine Einträge gemacht wurden.
Dazu habe ich beim Anlegen der Tabelle eine Zeile mit Leerstrings eingetragen.

Code: Alles auswählen

sql = "CREATE TABLE Nachrichten(Zeitstempel FLOAT, Nickname TEXT, Nachricht TEXT)"
    cursor.execute(sql)
    connection.commit()
    sql = "INSERT INTO Nachrichten VALUES(0,'','')"      <---- Zeile mit Leerstrings
    cursor.execute(sql)
    connection.commit()
Nun kann ich über den folgende Code testen, ob eine Zelle leer ist:

Code: Alles auswählen

connection = sqlite3.connect ("Datenbank/"+Leitungsname+".db")
   cursor = connection.cursor()
   sql = "SELECT * FROM Nachrichten ORDER BY Zeitstempel DESC"
   cursor.execute(sql)
   connection.commit()
   row = cursor.fetchone()
   
   if (row[1] != ""): 
       etc...
Diese Lösung finde ich aber sehr unschön.

Jetzt hab ich lange (wirklich lange, also bitte keine "bei SQlite nachgucke" posten) nachgeschaut, ob man nicht eine Zelle oder Tabellenzeile nach nicht angelegt prüfen kann. Ich bin immer nur auf solche (oder ähnliche, die ich probierte) Lösungen gestoßen:

Code: Alles auswählen

if (row[0] != None):
Allerdings wirft das die folgende Fehlermeldung:

Code: Alles auswählen

A problem occurred in a Python script. Here is the sequence of function calls leading up to the error, in the order they occurred.
 /home/www/web4/html/cgi-bin/Telegrafenleitung3/Telegrafenleitung3b.cgi in ()
  102    row = cursor.fetchone()
  103    aktZeit = time.time()
  104    if (row[0] != None):
  105      eingetrageneZeit = row[0]
  106      Nick = row[1]
row = None, builtin None = None

<type 'exceptions.TypeError'>: 'NoneType' object is unsubscriptable
      args = ("'NoneType' object is unsubscriptable",)
      message = "'NoneType' object is unsubscriptable" 
Wie frage ich richtig, ob eine Zelle / Zeile existiert?

Danke schonmal
mintpc
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

mintpc hat geschrieben:ich möchte prüfen, ob eine Tabelle noch leer ist, d.h. ob noch keine Einträge gemacht wurden.
Dazu habe ich beim Anlegen der Tabelle eine Zeile mit Leerstrings eingetragen.
Ich arbeite täglich mit Datenbanken und bei solchen obskuren Lösungen dreht sich mir der Magen um.

Was spricht denn gegen ein "SELECT COUNT(*) FROM tabellenname"?
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,
ich möchte prüfen, ob eine Tabelle noch leer ist, d.h. ob noch keine Einträge gemacht wurden.
Dazu habe ich beim Anlegen der Tabelle eine Zeile mit Leerstrings eingetragen.
Damit wäre die Tabelle schon nicht mehr leer. ;-)

Das ist aber alles viel zu umständlich! Wie \me schon sagt:

SELECT COUNT(*) FROM meine_tabelle

Wenn das Ergebnis der Abfrage "None" ist, ist die Tabelle leer. Ganz einfach. :-)

Gruß, noisefloor
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

noisefloor hat geschrieben:Wenn das Ergebnis der Abfrage "None" ist, ist die Tabelle leer. Ganz einfach. :-)
Das Ergebnis sollte eher 0 sein, denn ein Ergebnis bekommt man auf jeden Fall.
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

ja, hast' Recht...

"None" bekommt man bei

SELECT * FROM meine_tabelle

auf eine leere Tabelle.

Gruß, noisefloor
mintpc
User
Beiträge: 50
Registriert: Montag 23. Januar 2012, 12:44

Hallo zusammen.

Wie setzt ich den Code nun aber zusammen? So etwa?

Code: Alles auswählen

connection = sqlite3.connect ("Datenbank/"+Leitungsname+".db")
   cursor = connection.cursor()
   sql = "SELECT * FROM Nachrichten"
   cursor.execute(sql)
   connection.commit()
   if  (cursor != None):                    <------ oder hier: if (cursor != 0):   ???
      etc ... 

Wäre das nun richtig und "guter" Code?
Mehr als diese Zeilen kann ich mir aus meinem Python-Buch nicht herleiten.

Und nochwas. Was meint die Fehlermeldung, die ich oben zitiert habe, eigentlich genau?
mintpc hat geschrieben:<type 'exceptions.TypeError'>: 'NoneType' object is unsubscriptable
miptpc
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Zunächst einmal könntest Du Deinen Code in Python-Code-Tags setzen und dazu noch richtig einrücken! Die Ebenen stimmen ja mal gar nicht.

Zudem solltest Du doch fir Funktion `count(*)` verwenden - wo ist die?

Bei SQL-Statements, die nichts am Zustand der DB ändern braucht es kein `commit`.

Strings solltest Du nicht mittels `+` zusammensetzen, sondern z.B. der `format`-Methode. Bei Pfadnamen solltest Du auch auf `os.path`join` zurückgreifen:

Code: Alles auswählen

connection = sqlite3.connect(os.path.join("Datenbank", "{}.db".format(Leitungsname)))
Ich würde es so angehen:

Code: Alles auswählen

cursor.execute("select count(*) from table")
if cursor.fetchone():
    # hier gehts rein, wenn schon etwas in der Tabelle drin steht,
    # also `fetchone()` irgend etwas > 0 zurückliefert
    pass
Was ist denn das für ein Buch?
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Hyperion hat geschrieben:

Code: Alles auswählen

cursor.execute("select count(*) from table")
if cursor.fetchone():
    # hier gehts rein, wenn schon etwas in der Tabelle drin steht,
    # also `fetchone()` irgend etwas > 0 zurückliefert
    pass
fetchone() muss hier ducrch das "SELECT COUNT(*)" immer genau ein Ergebnis liefern.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

/me hat geschrieben: fetchone() muss hier ducrch das "SELECT COUNT(*)" immer genau ein Ergebnis liefern.
Und was willst Du mir damit sagen?

Edit: Ach so... Hab den Index vergessen :oops:

Code: Alles auswählen

if cursor.fetchone()[0]:
Zuletzt geändert von Hyperion am Donnerstag 26. Januar 2012, 20:01, insgesamt 1-mal geändert.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
mintpc
User
Beiträge: 50
Registriert: Montag 23. Januar 2012, 12:44

Aha, ok, "selectcount" liefert mir also die Anzahl der Zeilen der Tabelle. Also 0, wenn
es noch keine Zeilen gibt. Verstanden.
Hyperion hat geschrieben:Strings solltest Du nicht mittels `+` zusammensetzen, sondern z.B. der `format`-Methode. Bei Pfadnamen solltest Du auch auf `os.path`join`
Aha, ok. Werde ich machen. Warum ist das mit den "+" denn nicht gut?
Hyperion hat geschrieben:Was ist denn das für ein Buch?
Na, immer noch das von Thomas Theis. Ich hab mir jetzt aber schon das "Python Praxisbuch" von Farid Hajji bestellt.
Ist das besser? Teurer auf jeden Fall.

Vielen Dank für die Korrekturen

mintpc
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

mintpc hat geschrieben:Aha, ok, "selectcount" liefert mir also die Anzahl der Zeilen der Tabelle. Also 0, wenn
es noch keine Zeilen gibt. Verstanden.
"SELECT COUNT". Zwei Worte.

Du hast aktuell halt die Schwierigkeit zwei Sprachen zu lernen. Python und SQL.
mintpc
User
Beiträge: 50
Registriert: Montag 23. Januar 2012, 12:44

/me hat geschrieben:"SELECT COUNT". Zwei Worte.
Ja, sorry. Hab ich unsauber aufgeschrieben.
Trotzdem Danke für den Hinweis.

mintpc
BlackJack

@mintpc: Englisch „to subscript” heisst indexieren. „Unsubscriptable” dementsprechend, dass das nicht geht. Und in dem speziellen Fall beim einem Objekt vom Typ `NoneType`. Also:

Code: Alles auswählen

In [18]: type(None)
Out[18]: <type 'NoneType'>

In [19]: None[42]
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)

/home/bj/<ipython console> in <module>()

TypeError: 'NoneType' object is unsubscriptable
BlackJack

@Hyperion: Ob man bei SQL-Anweisungen die nichts am Inhalt der DB ändern, ein `commit()` braucht oder nicht, hängt von der Anweisung und vom Transaktionsverhalten des DBMS ab. Wenn das „repeatable read” garantiert, dann kann man unter Umständen sehr wohl ein `commit()` benötigen. Falls man es nicht *benötigt* kann man aber immer noch Ressourcen sparen wenn man die Transaktion explizit beendet.
Antworten