Android SQLite: Tabellenwert vom Typ Integer um 1 inkrementieren

  • Antworten:22
  • Bentwortet
Wdmprojekt
  • Forum-Beiträge: 33

29.01.2011, 14:29:08 via Website

Hallo,

leider funktioniert bei mir nicht das Inkrementieren eines Tabellenfeldes in der DB.
In der Regel schreibt man in SQL bzw SQLite Spaltenname = Spaltenname+1.

Mein Code verursacht äußerst fragwürdige Ergebnisse nach gleichem Prinzip.
Weiß jemand wie es richtig geht?

1public boolean incrementField() {
2
3 ContentValues args = new ContentValues();
4
5 // Variante 1
6 args.put(KEY_NAME, KEY_NAME+1); // Ergebnis ist immer der Wert KEY_NAME
7
8 // Variante 2
9 args.put(KEY_NAME, +1); // Ergebnis ist immer der Wert 1 in dem Tabellenfeld
10
11 return mDb.update(DATABASE_TABLE, args, "_id=1", null) > 0;
12}

— geändert am 29.01.2011, 14:29:38

Antworten
Mac Systems
  • Forum-Beiträge: 1.727

29.01.2011, 14:40:05 via Website

Weil du auch nur 1 in die ContentValues schreibst, evtl verstehst du das Problem besser wenn du -1 einträgst!

Windmate HD, See you @ IO 14 , Worked on Wundercar, Glass V3, LG G Watch, Moto 360, Android TV

Antworten
Wdmprojekt
  • Forum-Beiträge: 33

29.01.2011, 14:45:27 via Website

Bei der 1. Variante schreibe ich nicht 1 in das Tabellenfeld.

Dort halte ich es nach dem Prinzip: Spalte = Spalte+1
Hier ist das Ergebnis jedoch immer der Wert KEY_NAME.

Die 2. Variante schreibt in der Tat bei +1 den Wert 1, bei +5 den Wert 5,
sowie bei negativen Zahlen nz den Wert -nz.

Das Problem verstehe ich. Nur ist die Lösung KEY_NAME = KEY_NAME+1 nicht effektiv :)

Antworten
Ansgar M
  • Forum-Beiträge: 1.544

29.01.2011, 14:52:32 via App

Nur ne Idee, aber ist KEY_NAME ein String?
Lg Ansgar

Antworten
Wdmprojekt
  • Forum-Beiträge: 33

29.01.2011, 14:53:56 via Website

Ja, das ist ein String.

public static final String KEY_NAME = "counter";

OMG, ja, das ist ein String!

Hier muss natürlich ein Cursorobjekt hin a la Cursor query = mDb.query();

Integer.valueOf(query.getColumnIndexOrThrow(KEY_NAME))+1

— geändert am 29.01.2011, 15:04:31

Antworten
Wdmprojekt
  • Forum-Beiträge: 33

29.01.2011, 15:20:35 via Website

Schade, die Inkrementierung um 1 funktioniert immer noch nicht :(

1public boolean incrementField() {
2 // Get the current data from table
3 Cursor query = mDb.rawQuery("SELECT "+KEY_NAME+" FROM "+DATABASE_TABLE+" WHERE _id=1", null);
4
5 if (query != null) {
6 query.moveToFirst();
7 }
8
9 int newValue = Integer.valueOf(query.getColumnIndexOrThrow(KEY_NAME))+1;
10
11 query.close();
12
13 ContentValues args = new ContentValues();
14 args.put(KEY_NAME, newValue);
15
16 return mDb.update(DATABASE_TABLE, args, "_id=1", null) > 0;
17 }

— geändert am 29.01.2011, 15:41:46

Antworten
Wdmprojekt
  • Forum-Beiträge: 33

29.01.2011, 15:59:52 via Website

Keiner eine Idee???

Antworten
San Blarnoi
  • Forum-Beiträge: 2.545

29.01.2011, 17:57:21 via Website

Warum nicht die einfache, direkte Lösung?

mDb.rawQuery("update "+DATABASE_TABLE+" set "+KEY_NAME+"="+KEY_NAME+"+1 where _id=1", null);

Antworten
Wdmprojekt
  • Forum-Beiträge: 33

29.01.2011, 18:11:19 via Website

Bewirkt leider auch nichts, obwohl es logisch aussieht...

— geändert am 29.01.2011, 18:18:04

Antworten
San Blarnoi
  • Forum-Beiträge: 2.545

29.01.2011, 18:59:23 via Website

Sieht nicht nur logisch aus ;)
Alle meine Apps nutzen ausschließlich rawQuery() für select/update/insert/delete Statements und funktionieren einwandfrei.

Wenn das bei dir nicht geht, muss es somit einen anderen Grund dafür geben;
  • "_id=1" ist korrekt?
  • Die Zeile wird erreicht und ausgeführt?
  • Die Verifizierung des Ergebnisses ist über jeden Zweifel erhaben? (Datenbank mal auf dem PC angeschaut?)
  • Die Inhalte von DATABASE_TABLE und KEY_NAME sind korrekt? (probiere das Statement mal mit direkt eingesetzten Namen)
  • Die Funktion incrementField() besteht nur noch aus dieser Zeile?

Antworten
Wdmprojekt
  • Forum-Beiträge: 33

29.01.2011, 19:04:21 via Website

and dev
Sieht nicht nur logisch aus ;)
Alle meine Apps nutzen ausschließlich rawQuery() für select/update/insert/delete Statements und funktionieren einwandfrei.

Wenn das bei dir nicht geht, muss es somit einen anderen Grund dafür geben;
  • 1) "_id=1" ist korrekt?
  • 2) Die Zeile wird erreicht und ausgeführt?
  • 3) Die Verifizierung des Ergebnisses ist über jeden Zweifel erhaben? (Datenbank mal auf dem PC angeschaut?)
  • 4) Die Inhalte von DATABASE_TABLE und KEY_NAME sind korrekt? (probiere das Statement mal mit direkt eingesetzten Namen)
  • 5) Die Funktion incrementField() besteht nur noch aus dieser Zeile?

Mich freut es, dass Du mich systematisch durch das praktische Debugging führst. Habe hier noch wenig Erfahrung!

  • 1) "_id=1" ist korrekt
  • 2) Wie prüfe ich das?
  • 3) Wo finde ich die DB auf dem PC?
  • 4) DATABASE_TABLE entspricht apptable und KEY_NAME entspricht counter
  • 5) Nein. Es existiert noch die Zeile mit dem boolischen Rückgabewert true

— geändert am 29.01.2011, 21:08:35

Antworten
San Blarnoi
  • Forum-Beiträge: 2.545

29.01.2011, 22:57:28 via Website

1) Hm, aber nur testweise, oder?
Ansonsten klingt ein konstanter PKEY nicht nach einer Anwendung für eine Datebank ;)


2) Breakpoint setzen oder mittels Log.d() eine Ausgabe generieren, etwa

Log.d("inc", "vor update");
mDb.rawQuery(...);
Log.d("inc", "nach update");
return true;

Die Ausgaben siehst du dann in der Debug-Perspektive, da findest du ggf auch Fehlermeldungen etc.


3) Wenn du so fragst: gar nicht ;)
Deine App öffnet die DB ja irgendwo, und von dort müsstest du sie vom Device/Emu auf den PC kopieren


4) Dann ändere das Statement mal testweise zu
mDb.rawQuery("update apptable set counter=counter+1 where _id=1", null);

Antworten
Wdmprojekt
  • Forum-Beiträge: 33

30.01.2011, 14:01:19 via Website

Log Messages sind alle in Ordnung, Update wirft keine Fehlermeldung.
Nun kann es nur noch daran liegen, dass die TextViews nicht aktualisert werden.

Die update() Methode befindet sich in meinem Datenmodell DB.java
Aufgerufen wird die Methode in List.java
Gesehen werden soll das Update in Stats.java

Hierbei muss noch irgendwas schief gehen, daher poste ich folgend einmal meine relevanten Methoden.

DB.java
1public boolean incrementField() {
2 Log.d("inc", "vor update"); // erscheint in Konsole
3 mDb.rawQuery("UPDATE apptable SET counter=counter+1 WHERE _id=1", null); // _id=1 for testing
4 Log.d("inc", "nach update"); // erscheint in der Konsole ohne vorangehender Fehlermeldung
5 return true;
6 }
7
8public HashMap<String,String> getStats() {
9Cursor query = mDb.rawQuery("SELECT * FROM "+DATABASE_TABLE+" WHERE _id=1", null);
10
11 if (query != null) {
12 query.moveToFirst();
13 }
14
15HashMap<String,String> stats = new HashMap<String,String>();
16stats.put(KEY_NAME, query.getString(query.getColumnIndexOrThrow(KEY_NAME)));
17
18return stats;
19}

Stats.java
1@Override
2 public void onCreate(Bundle savedInstanceState) {
3 Log.v(TAG, "Activity State: onCreate()");
4 super.onCreate(savedInstanceState);
5 drawUI();
6 }
7
8@Override
9 public void onStart() {
10 super.onStart();
11 drawUI();
12 }
13
14@Override
15 protected void onResume() {
16 super.onResume();
17 drawUI();
18 }
19
20public void drawUI() {
21[...]
22TexView counter = (TextView) findViewById(R.id.counter);
23
24HashMap<String,String> stats = mDbHelper.getStats();
25counter.setText(stats.get(DB.KEY_NAME));
26}

— geändert am 30.01.2011, 14:02:27

Antworten
Mac Systems
  • Forum-Beiträge: 1.727

30.01.2011, 14:52:01 via Website

Datenbank aus dem Emulator laden und mit FF Plugin SQLite Manager überprüfen half bei mir fast immer.

Windmate HD, See you @ IO 14 , Worked on Wundercar, Glass V3, LG G Watch, Moto 360, Android TV

Antworten
Wdmprojekt
  • Forum-Beiträge: 33

30.01.2011, 16:41:03 via Website

Ich bin zu dem Ergebnis gekommen, dass es mit rawQuery() Schwierigkeiten gibt
und sich diese eher für das Lesen eignet. Nun verwende ich execSQL() erfolgreich :)

1mDb.execSQL("UPDATE apptable SET counter=counter+1 WHERE _id=1");

— geändert am 30.01.2011, 16:43:17

Antworten
Markus Gu
  • Forum-Beiträge: 2.644

30.01.2011, 16:44:01 via Website

Wdmprojekt
Ich bin zu dem Ergebnis gekommen, dass es mit rawQuery() Schwierigkeiten gibt
und sich diese eher für das Lesen eignet. Nun verwende ich execSQL() wobei nun
folgender Fehler auftaucht:

01-30 15:39:27.371: ERROR/AndroidRuntime(1062): java.lang.IllegalArgumentException: Empty bindArgs

zwischen rawquery und execsql gibt es aber schon einen unterschied

rawquery, wie der name schon sagt, für ein query aus, das einen cursor zurückliefert => SELECT
execsql führt ein sql statement aus, UPDATE, DELETE, INSERT


die android doku erklärt hierzu eigentlich alles wichtige

swordiApps Blog - Website

Antworten
Wdmprojekt
  • Forum-Beiträge: 33

30.01.2011, 16:51:54 via Website

Zuletzt noch eine rhetorische Frage:

Warum melden sich die Besserwisser immer erst, wenn das Problem gelöst wurde?

Antworten
Ansgar M
  • Forum-Beiträge: 1.544

30.01.2011, 16:59:20 via App

Der Weg ist das Ziel :grin:
Sorry, aber das musste sein ;)
Lg Ansgar

Antworten
Wdmprojekt
  • Forum-Beiträge: 33

30.01.2011, 17:05:05 via Website

*Schmunzel* -_-

Antworten
Markus Gu
  • Forum-Beiträge: 2.644

30.01.2011, 18:49:24 via Website

ein wenig eigeninitiative wird ja wohl nicht zu viel verlangt sein. ;)

sei froh, dass dir hier so tatkräftig geholfen wird.

swordiApps Blog - Website

Gelöschter Account

Antworten
Wdmprojekt
  • Forum-Beiträge: 33

30.01.2011, 20:28:01 via Website

Selbstverständlich, ist auch alles in Ordnung :D

Antworten
Dominic Bartl
  • Forum-Beiträge: 180

31.01.2011, 09:41:33 via Website

Anscheinend is das Problem schon gelöst aber ich glaub, wenn ich das richtig verstanden hab, willst du die ID jedes mal um 1 erhöhen.
Anstatt da jedes Mal eine neue Datenbankabfrage zu machen sollte man das einfach der Datenbank das selber überlassen.

Du leitest einfach von der Klasse SQLiteOpenHelper und in der onCreateMethode...
1db.execSQL("create table " + TABLE_NAME + " (" +
2 BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
3 KEY_NAME + " TEXT UNIQUE NOT NULL," +
4 KEY_ACTIVE + " INTEGER," +
5 KEY_CONDITIONS + " TEXT," +
6 KEY_SETTINGS + " TEXT);");

Also es geht um das AUTOINCREMENT

Grüße :grin:

Antworten