Sql Abfrage mit String vergleichen

  • Antworten:13
  • Bentwortet
Tanja Z.
  • Forum-Beiträge: 52

16.04.2011, 20:46:14 via Website

Hallo!

Ich habe ein Problem bei dem ich nicht weiterkomme:

Ich erzeuge über eine Schleife Strings, die mit einer Datenbank-Spalte verglichen werden sollen und nur dann in die Tabelle abgespeichert werden sollen, wenn diese nicht übereinstimmen. Wie kann ich das Problem lösen?

Speicher.java
1public Cursor ladeDetails (long id) {
2 return mDb.getReadableDatabase().query(
3 Tbl.TABLE_NAME, Tbl.ALL_COLUMNS,
4 null, null, null, null, null);
5 }

Main.java

1final Cursor myCursor = mSpeicher.ladeDetails(Id);
2startManagingCursor(myCursor);
3
4if (??????) {
5
6}


Habe es probiert mit !myCursor.equals(i) und Tbl.Name.equals(i), aber "i" wird trotzdem in die Datenbank gespeichert, obwohl bereits gleiche Daten in der Datenbank vorhanden sind.


Grüße,

Tanja

Antworten
Markus B.
  • Forum-Beiträge: 636

16.04.2011, 21:31:16 via Website

Hi,
das Problem lässt sich einfach lösen.
Spontan fallen mir hier zwei Lösungen ein:

1.
Du kannst die entsprechende Spalte unique machen und dann bekommst du beim Einfügen eines vorhanden Datensatzes eine Fehlermeldung.
Diese kannst du dann in einem try catch behandeln. Diese Lösung ist ziemlich simpel, ist meiner Meinung nach aber ein schlechter Stiel.

2.
Du lädst den Inhalt der Spalte und vergleichst alle Werte mit dem entsprechenden Wert, welcher in die DB geschrieben werden soll.
Hier kommt es aber darauf an wie viele Datensätze in der entsprechenden Spalte vorhanden sein werden. Bei großen Datenmenge wir die Performance der Anwendung leiden.
Wie folgt kannst du dann die Werte Vergleichen:
1final String myString = "new_entry";
2final Cursor myCursor = db.query(...);
3boolean contains = false;
4
5if(0 < myCursor.getCount)
6{
7 while(myCursor.moveToNext())
8 {
9 final String dbString = myCursor.getString(0) // Hier ist natürlich vorausgesetzt das dein Query die Strings zum Vergleichen liefert.
10 if(dbString.equals(myString)
11 {
12 contains = true;
13 break;
14 }
15 }
16}
17
18if(!contains)
19{
20 // Insert myString in die db
21}

Das wären meine Ideen zu diesem Thema.

Gruß,
Markus

— geändert am 16.04.2011, 23:36:48

Antworten
Gelöschter Account
  • Forum-Beiträge: 281

16.04.2011, 23:15:26 via Website

Wie wäre es den damit, per Select-Statement für jeden String zu prüfen, ob es ihn schon gibt? Wenn das Ergebnis der Abfrage keine Datensätze liefert, gibt es den String noch nicht in der Tabelle...

Antworten
Tanja Z.
  • Forum-Beiträge: 52

17.04.2011, 00:03:55 via Website

Hallo Markus!

Hab mich für die zweite Variante entschieden. Funktioniert einwandfrei! Vielen Dank!



Gruß, Tanja

Antworten
Tanja Z.
  • Forum-Beiträge: 52

17.04.2011, 00:16:05 via Website

Hallo Thomas!

Es handelt sich um eine Variable, der Wert kann sich ändern, sobald der User eine andere Eingabe macht. Du meinst die Variable in ein Where-Statement einbinden?

Gruß, Tanja

Antworten
Gelöschter Account
  • Forum-Beiträge: 281

17.04.2011, 11:51:19 via Website

Ja - genau.

Antworten
Tanja Z.
  • Forum-Beiträge: 52

22.04.2011, 21:47:03 via Website

Hallo!

Ich belasse es bei der von Markus vorgeschlagenen 2. Variante , funktioniert auch. Trotzdem danke!

Gruß,

Tanja

— geändert am 22.04.2011, 21:48:29

Antworten
Gelöschter Account
  • Forum-Beiträge: 281

22.04.2011, 22:29:39 via Website

Und liest jedesmal alle Datensätze? Nicht sehr performant...

Antworten
Markus B.
  • Forum-Beiträge: 636

22.04.2011, 22:51:14 via Website

Thomas M.
Und liest jedesmal alle Datensätze? Nicht sehr performant...

Hi,
da muss ich Thomas zustimmen. Ich weiß auch nicht mehr so ganz, warum ich die entsprechende Lösung mit dem select nicht gleich am Anfang aufgeführt habe...
Wobei ich hier nicht die Performance als Grund für eine Umstellung aufzählen würde. (Ich unterstelle einfach mal deine App arbeitet nicht mit Hunderten Einträgen in der entsprechenden Spalte.)
Es geht hier ehr darum, ob dein Code einen guten Stiel wiederspiegel soll :) Somit würde ich unter diesem Aspekt eine Umstellung schon lohnen.
Aber das ist nur meine bescheidende Meinung :P

Gruß,
Markus

Antworten
Gelöschter Account
  • Forum-Beiträge: 5.136

22.04.2011, 23:18:50 via Website

Moin,

ich bin ja in SQLite nicht so bewandert aber würde nicht eine query so etwa wie :


insert or replace into mdat values (NULL, 'kdkdk');

dem Zweck auch dienlich sein?

(Bei einer angenommenen Struktur wie:
CREATE TABLE "mdat" ("id" INTEGER PRIMARY KEY NOT NULL UNIQUE , "text" VARCHAR NOT NULL UNIQUE )
)

Im Grunde wird hierbei entweder eine neue Row eingefügt wenn die Unique Spalte mit dem String Wert noch nicht existiert, oder aber die bestehende Spalte mit einem neuen Autoincrement Value der ersten Spalte aktualisiert.

Sofern der Id Wert der ersten Spalte egal ist, erfüllt das genau den Zweck und ist wesentlich Ressourcen schonender und eleganter als alle Spalten zunächst mal einzulesen und dann auszuwerten.

Zumindest bei mir hat es als Trockenübung in einer einfachen SQLite DB wie oben angegeben funktioniert.

lg Voss

Antworten
Gelöschter Account
  • Forum-Beiträge: 281

23.04.2011, 08:10:13 via Website

Auch die Lösung könnte es sein, allerdings würde soweit ich mich auskenne im Replace-Falle der "alte" Datensatz gelöscht (nicht geupdated) - was zur Folge hätte, dass eventuelle Lösch-Trigger oder Cascading Deletes auch ausgelöst würden. Könnte also tendenziell ungewünscht sein.

— geändert am 23.04.2011, 08:21:43

Antworten
Gelöschter Account
  • Forum-Beiträge: 5.136

23.04.2011, 13:00:07 via Website

Hab gerade noch mal in der Doku nachgelesen ...

insert or fail into mdat values (NULL, 'gjgjgjg');

Das sollte dann die passende Lösung sein.

lg Voss

Antworten
Gelöschter Account
  • Forum-Beiträge: 281

23.04.2011, 16:08:40 via Website

Das klingt gut.

Antworten
Tanja Z.
  • Forum-Beiträge: 52

23.04.2011, 22:18:50 via Website

Das ist ein echt nettes Forum.

Ich speichere den jeweiligen Datensatz wie folgt ab:

final ContentValues daten = new ContentValues();
daten.put(TageTbl.DATUM, datum);
Allerdings wird dieser dann mehrfach abgespeichert, weil ich diesen über eine Schleife ermittele.


Gruß,

Tanja

Antworten