Sqlite rawquery cursor.getCount = 0

  • Antworten:17
Wicki11
  • Forum-Beiträge: 103

05.03.2018, 17:10:34 via Website

Hallo,
ich habe 2 Tabellen in einer SQLite-DB, auf die ich problemlos zugreifen kann.
friends-Tabelle:
CREATE TABLE friends (_id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(20) NOT NULL, forename VARCHAR(20) NOT NULL, birthday DATE);
books-Tabelle:
CREATE TABLE books (_id INTEGER PRIMARY KEY AUTOINCREMENT, bookname VARCHAR(20) NOT NULL, owner_id INTEGER NOT NULL);

Nun will ich folgendes SELECT ausführen lassen um kombinierte Daten zu empfangen:
select name,forename,bookname from friends,books where friends._id = books.owner_id
Außerhalb von Android (Windows SQLite3) funktioniert das SELECT wie erwartet, in meiner App jedoch wird ein leerer Cursor zurückgegeben. Die beiden Tabellen friends,books existieren in der DB und die SELECT-Anweisung soll deren Daten kombiniert angeben und diese sollen über einen SimpleCursorAdapter in einer ListView verarbeitet werden.
Ich vermute, dass die where-Klausel (mit _id) verantwortlich ist.
Codeausschnitt:

String sql = "select name,forename,bookname from friends,books where friends._id =
books.owner_id";
Cursor c = db.rawQuery(sql,null);
c.moveToLast();
int i1 = c.getCount(); //liefert 0

Bitte um Hilfe !

— geändert am 05.03.2018, 17:15:20

Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

05.03.2018, 17:15:04 via Website

Hallo Wicki,
du solltest auch 2 Tabellen nicht meit Select und where sondern mit join verbinden, so wie es in SQL Standard ist.
https://stackoverflow.com/a/4957197

select f.name,f.forename,b.bookname from friends  f
inner join books b on f._id = b.owner_id 

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Kommentieren
Wicki11
  • Forum-Beiträge: 103

05.03.2018, 17:32:46 via Website

Zunächst Dank für die schnelle Antwort.
Allerdings hat sich am Ergebnis nichts geändert mit diesem Code:

sql="select f.name,f.forename,b.bookname from friends f inner join books b on f._id =   b.owner_id";
Cursor c = db.rawQuery(sql,null);
c.moveToLast();
int i1 = c.getCount();  //weiterhin 0
Hilfreich?
Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

05.03.2018, 17:37:30 via App

Und du bist dir sicher, dass du Daten in der DB hast?
Dann probier mal ein left Join vlt stimmen deine IDs nicht

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Kommentieren
Wicki11
  • Forum-Beiträge: 103

05.03.2018, 17:45:22 via Website

Die beiden Tabellen kann ich in der gleichen App jede einzeln antippen und all ihre Daten in einer ListView ansehen. Die Datenbank habe ich über Androids DDMS auf den PC kopiert und dort funktioniert das SELECT.

Hilfreich?
Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

05.03.2018, 17:49:44 via App

Du machst auch moveToLast warum?
Mach mal ein MoveToFirst und dann ein count und wie gesagt das left Join

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Kommentieren
Wicki11
  • Forum-Beiträge: 103

05.03.2018, 18:15:59 via Website

mit dem left join wird der Cursor gefüllt ! Allerdings kommt nun bei der Erzeugung des Adapters für Cursor und ListView ein Fehler:
java.lang.IllegalArgumentException: column '_id' does not exist

anzeigeSpalten = new String[]{"name", "forename", "bookname"};
anzeigeViews = new int[]{R.id.textViewName, R.id.textViewVorname, R.id.bookname};
int i1 = cursor.getCount(); //zeigt jetzt den Wert 8 an
adapter = new SimpleCursorAdapter(this, R.layout.buchsatz, cursor,anzeigeSpalten, anzeigeViews);

bei der adapter-Anweisung kommt der Fehler !

Hilfreich?
Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

05.03.2018, 21:24:09 via App

Dachte ich mir.
Du selektierst die Spalte _id nicht somit kannst du die auch nicht aus dem Cursor auslesen.

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Kommentieren
Wicki11
  • Forum-Beiträge: 103

05.03.2018, 21:44:16 via Website

Ich will sie ja auch gar nicht aus dem Cursor auslesen, in anzeigeSpalten steht nichts von _id (siehe adapter-Anweisung). Welche _id-Spalte (friends oder books) sollte ich denn selektieren und wozu, die brauche ich doch nicht. Oder braucht rawQuery immer eine _id-Spalte ? auch wenn die Spalten nicht aus einer einzelnen Tabelle sondern aus 2 Tabellen kommen ?

Hilfreich?
Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

05.03.2018, 21:50:04 via App

Die Select braucht das nicht, aber dein CursorAdaptor:
https://stackoverflow.com/a/8090467
Von daher musst du entweder ein CustomAdapter nutzen und den Cursor selber lesen oder eine _id includen.

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Kommentieren
Wicki11
  • Forum-Beiträge: 103

05.03.2018, 22:02:06 via Website

Verstehe ich das richtig mit dem includen:
in anzeigeSpalten und anzeigeViews muss ich ein zusätzliches Element einsetzen für die _id, die ich aus einer der beiden Tabellen nehmen kann ?

Hilfreich?
Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

05.03.2018, 22:30:16 via App

Ne in der anzeige nicht nur im Cursor sprich im Select muss die id selektiert werden.

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Wicki11
Kommentieren
Wicki11
  • Forum-Beiträge: 103

05.03.2018, 23:00:37 via Website

Jetzt scheint alles zu funktionieren, ich muss morgen nochmal die gesamte App (auch mit der Anzeige der in der DB vorhandenen Tabellen) überprüfen.
Auf alle Fälle danke ich Dir vielmals, Du hast mir sehr geholfen !

Hilfreich?
Kommentieren
Wicki11
  • Forum-Beiträge: 103

06.03.2018, 10:39:36 via Website

Habe heute nochmal alles überprüft. Dabei habe ich festgestellt, dass die SELECT-Anweisung mit dem left join auch Beiträge bereitstellt, in denen es keine Kopplung zwischen friends und books gibt, d.h. in der friends-Tabelle gibt es Einträge deren _id nicht in einem owner_id der books-Tabelle erscheint. Mit anderen Worten es gibt friends die keine books haben.
Deshalb habe ich die SELECT-Anweisung nochmal geändert indem ich die WHERE-Klausel wieder eingeführt habe:
select friends._id, name,forename,bookname from friends,books where friends._id = books.owner_id Das funktioniert wie beabsichtigt.
Der left join kombiniert also alle Einträge, die WHERE-Klausel wirkt einschränkend.

Trotzdem nochmal vielen Dank an Pascal, der mich auf die richtige Spur gebracht hat !

— geändert am 06.03.2018, 10:46:14

Hilfreich?
Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

06.03.2018, 11:34:33 via App

Jupp das mit dem left join sollte auch nur ein Test sein, left join zeigt auch Personen an für die kein kein Buch gibt.
Wenn es jetzt so geht dann ist doch gut :)

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Kommentieren
Frank Rudolf
  • Forum-Beiträge: 215

06.03.2018, 11:34:34 via Website

Für das letztere Problem gibt es aber in SQL Sprachkonstrukte, die das bewältigen. Ohne genauer nachzuschlagen, fällt mir das Wort outer hierzu ein (left outer, right outer etc.) Was genau passt, kann ich mir auch nie merken.

Vielleicht könnte das helfen.

Hilfreich?
Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

06.03.2018, 11:35:17 via App

@Frank er bräuchte hier ein inner join wenn er es ohne where clause machen wöllte.

— geändert am 06.03.2018, 11:35:30

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Kommentieren
Frank Rudolf
  • Forum-Beiträge: 215

07.03.2018, 17:20:43 via Website

@Frank er bräuchte hier ein inner join wenn er es ohne where clause
machen wöllte.

Vieles geht ja auch so, wie er es gemacht hat. Aber schulmäßig ist natürlich der Gebrauch des Joins. Und das Wort outer ist wohl implizit schon in diesen right- oder left-Joins vorhanden, sodass man es eigentlich nicht mehr angeben braucht.

Wenn man left und right vertauscht, sieht man auch ganz gut die unterschiedlichen Ergebnisse (welche der Tabellen die Null-Werte hat etc.).

Hilfreich?
Pascal P.
Kommentieren