Der Umgang mit SQLite

  • Der Umgang mit SQLite

    Inhalt des Tutorials ist das Erstellen einer SQLite-Datenbank, das Anlegen von Tabellen, sowie das Einfügen, Ändern und Auslesen von Daten aus einer Datenbank-Tabelle.

    Dieses Tutorial wird etwas aufwendiger und besteht aus 3 activitys, nämlich der main-activity, der activity "fahrzeuge" auf der die gespeicherten Fahrzeuge in einer Liste ausgegeben werden und der activity "Fahrzeug_New" wo man ein neues Fahrzeug anlegen oder ein in der vorherigen activity selektiertes Fahrzeug bearbeiten kann.

    Alle Dateien die in diesem Tutorial angesprochen werden finden Sie im Anhang.

    Wie man ein Android-Projekt erstellt werde ich hier nicht erläutern da dies jedem klar sein sollte.

    Wir definieren also in der main-activity erst ein mal ein paar Variablen die wir im Programm öfter benutzen werden.

    MyDB bietet Methoden Verwalten einer SQLite-Datenbank. Dazu gehören das Erstellen und Löschen von Datenbanken und Tabellen, sowie das Ausführen von SQLAnweisungen.
    MY_DB_NAME ist der Name der Datenbank.
    MY_DB_TABLE ist die Tabelle die wir erzeugen wollen
    MENU_FAHRZEUGE repräsentiert die ID für unseren einzigen Menüpunkt über den wir zur nächsten activity gelangen.


    [size=large]Activity TankPro2[/size]

    Java-Quellcode

    1. public class TankPro2 extends Activity {
    2. SQLiteDatabase myDB = null;
    3. final static String MY_DB_NAME = "TankPro2";
    4. final static String MY_DB_TABLE = "fahrzeuge";
    5. static final int MENU_FAHRZEUGE = 1;






    Wir wollen, dass beim starten der Anwendung eine Verbindung zu unserer Datenbank aufgebaut wird. Dazu wird als erstes geprüft ob die Datenbank und die benötigten Tabellen überhaupt existieren. Sollte die Datenbank vorhanden sein, wird eine Verbindung zu dieser hergestellt. anderenfalls wird die Datenbank erzeugt und anschließend zu dieser verbunden. Das gleich geschieht mit unseren Datenbanktabellen. Sollte eine Tabelle nicht existieren, wird diese angelegt.

    Java-Quellcode

    1. @Override
    2. public void onCreate(Bundle savedInstanceState) {
    3. super.onCreate(savedInstanceState);
    4. onCreateDBAndDBTabled(); //DB und Tables erstellen wenn noch nicht vorhanden
    5. setContentView(R.layout.main);
    6. }






    Hier nun die Funktion zum erstellen der Datenbank und der Datenbanktabellen.

    Java-Quellcode

    1. private void onCreateDBAndDBTabled() {
    2. myDB = this.openOrCreateDatabase(MY_DB_NAME, MODE_PRIVATE, null);
    3. myDB.execSQL("CREATE TABLE IF NOT EXISTS " + MY_DB_TABLE
    4. + " (_id integer primary key autoincrement,
    5. name varchar(100),
    6. model varchar(100),
    7. bemerkungen varchar(255),
    8. kraftstoffart integer(3),
    9. tankinhalt integer(3))"
    10. +";");
    11. }
    Alles anzeigen


    Genauso können wir direkt in dieser Funktion SQL-Befehle zum löschen einer Tabelle oder zum einfügen von Daten in eine Tabelle angeben.


    Nun erstellen wir noch einen Menüpunkt über den wir zur nächsten
    activity „fahrzeuge“ gelangen. Dieser Menüpunkt wird nach anklicken
    des Menübuttons auf unserem Handy angezeigt.

    Java-Quellcode

    1. public boolean onCreateOptionsMenu(Menu menu) {
    2. super.onCreateOptionsMenu(menu);
    3. menu.add(0, MENU_FAHRZEUGE, 0, R.string.menuFahrzeuge)
    4. .setShortcut('1', 'f')
    5. .setIcon(R.drawable.menu_fahrzeuge);
    6. return true;
    7. }



    Nun müssen wir unseren Menüpunkt noch mit einer Aktion versehen.
    Es wird geprüft ob der Menüpunkt „MENU_FAHRZEUGE“ angeklickt wurde, anschließend wird die activity „fahrzeuge“ geladen und angezeigt.

    Java-Quellcode

    1. public boolean onOptionsItemSelected(MenuItem item){
    2. switch (item.getItemId()) {
    3. case MENU_FAHRZEUGE:
    4. Intent iFahrzeuge = new Intent(this, fahrzeuge.class);
    5. startActivity(iFahrzeuge);
    6. return true;
    7. }
    8. return false;
    9. }




    [size=large]Activity fahrzeuge[/size]

    Nun befinden wir uns auf der activity „fahrzeuge“ wo wir den Namen und das Model aller in der Datenbank gespeicherten Fahrzeuge in einer Liste ausgeben lassen.
    Außerdem wird es wieder einen Menüpunkt geben über den wir ein neues Fahrzeug anlegen können. Um die Daten eines Fahrzeuges zu bearbeiten klickt man in der Liste einfach auf den entsprechenden Eintrag, worauf die activity „Fahrzeug_New“ wie auch beim anklicken des Menüpunktes „Neues Fahrzeug“ gestartet und angezeigt wird nur das in diesem Fall die ID des Fahrzeuges mit übergeben wird.



    Wir connecten zu unserer Datenbank und lesen anschließend die _id, den Namen und das Model aller Fahrzeuge aus. Die Daten werden im SimpleCursorAdapter hinterlegt den wir anschließend mit unserer Liste verbinden.

    Java-Quellcode

    1. public class fahrzeuge extends ListActivity {
    2. SQLiteDatabase myDB = null;
    3. static final int MENU_NEW_KFZ = 0;
    4. public void onCreate(Bundle icicle) {
    5. super.onCreate(icicle);
    6. myDB = this.openOrCreateDatabase(TankPro2.MY_DB_NAME, MODE_PRIVATE, null);
    7. Cursor c = myDB.rawQuery("SELECT _id, name, model FROM " + TankPro2.MY_DB_TABLE + ";", null);
    8. startManagingCursor(c);
    9. SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
    10. android.R.layout.simple_list_item_1,
    11. c,
    12. new String[] { "_id" },
    13. new int[] { android.R.id.text1 });
    14. adapter.setViewBinder(new ViewBinder() {
    15. @Override
    16. public boolean setViewValue(View view, Cursor theCursor, int column) {
    17. String ColumnName = theCursor.getString(1); //Name
    18. String ColumnModel = theCursor.getString(2); //Model
    19. ((TextView)view).setText(ColumnName + ", " + ColumnModel);
    20. return true;
    21. }
    22. });
    23. this.setListAdapter(adapter);
    24. }
    Alles anzeigen






    Nun legen wir die Funktion „onListItemClick“ an die aufgerufen wird wenn wir einen Eintrag in der Liste anklicken.
    Es wird die activity „Fahrzeug_New“ gestartet und ihr die _id des angeklickten Eintrages übergeben.
    Das übergeben einer Variable an eine weitere activity geschieht über putExtra. PutExtra übergibt man den Namen der Variable und den zu übergebenden Wert.

    Java-Quellcode

    1. @Override
    2. protected void onListItemClick(ListView l, View v, int position, long id) {
    3. super.onListItemClick(l, v, position, id);
    4. Intent i = new Intent(this, Fahrzeug_New.class);
    5. i.putExtra("id", id);
    6. this.startActivity(i);
    7. }






    Jetzt erstellen wir wie in der vorhergehenden activity wieder ein Optionsmenü und hauchen ihm mit „onOptionsItemSelected“ Leben ein.

    Java-Quellcode

    1. public boolean onCreateOptionsMenu(Menu menu) {
    2. super.onCreateOptionsMenu(menu);
    3. menu.add(0, MENU_NEW_KFZ, 0, R.string.menuNewKFZ)
    4. .setShortcut('1', 'n')
    5. .setIcon(android.R.drawable.ic_menu_add);
    6. return true;
    7. }


    Java-Quellcode

    1. public boolean onOptionsItemSelected(MenuItem item){
    2. switch (item.getItemId()) {
    3. case MENU_NEW_KFZ:
    4. Intent iFahrzeug_new = new Intent(this, Fahrzeug_New.class);
    5. startActivity(iFahrzeug_new);
    6. return true;
    7. }
    8. return false;
    9. }




    [size=large]Activity Fahrzeug_New[/size]

    Diese activity ist etwas aufwendiger da wir mit ihr ein neues Fahrzeug anlegen oder aber ein zuvor auf der activity „fahrzeuge“ selektiertes Fahrzeug bearbeiten können.


    Diese activity wird von der activity „fahrzeuge“ aufgerufen sobald man ein Fahrzeug aus der Liste auswählt oder man auf den Menüppunkt „Neues Fahrzeug“ klickt.

    Wir haben uns gemerkt, das beim anklicken eines Fahrzeuges in der Liste, die _id des gewählten Fahrzeuges übergeben wird. Dies passiert nicht wenn man auf den Menüpunkt „Neues Fahrzeug“ klickt.

    Also müssen wir als erstes überprüfen ob eine _id übergeben wurde um entscheiden zu können ob ein neues Fahrzeug angelegt oder die Daten des gewählten Fahrzeuges aus der Datenbank geladen werden sollen.

    Diese Abfrage benötigen wir ein zweites mal bei der Frage ob die Daten neu in die Datenbank eingefügt (Neues Fahrzeug) oder geändert (Fahrzeug wurde in der Liste ausgewählt) werden sollen.

    Java-Quellcode

    1. public class Fahrzeug_New extends Activity {
    2. SQLiteDatabase myDB = null;
    3. static final int MENU_INSERT_KFZ = 0;
    4. static final int MENU_UPDATE_KFZ = 0;
    5. @Override
    6. public void onCreate(Bundle savedInstanceState) {
    7. super.onCreate(savedInstanceState);
    8. setContentView(R.layout.fahrzeug_new);
    9. Spinner s1 = (Spinner) findViewById(R.id.cb_KfzTreibstoffArt);
    10. ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
    11. this,
    12. R.array.Kraftstoffarten,
    13. android.R.layout.simple_spinner_item);
    14. adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    15. s1.setAdapter(adapter);
    16. if(getIntent().hasExtra("id") == true) {
    17. long l = getIntent().getExtras().getLong("id");
    18. myDB = this.openOrCreateDatabase(TankPro2.MY_DB_NAME,
    19. MODE_PRIVATE, null);
    20. Cursor myCursor = myDB.rawQuery("SELECT name,
    21. model,
    22. bemerkungen,
    23. kraftstoffart,
    24. tankinhalt
    25. FROM " + TankPro2.MY_DB_TABLE + "
    26. WHERE _id = "+l+";", null);
    27. startManagingCursor(myCursor);
    28. int ColumnName = myCursor.getColumnIndex("name");
    29. int ColumnModel = myCursor.getColumnIndex("model");
    30. int ColumnBemerkung = myCursor.getColumnIndex("bemerkungen");
    31. int ColumnKraftstoffart = myCursor.getColumnIndex("kraftstoffart");
    32. int ColumnTankinhalt = myCursor.getColumnIndex("tankinhalt");
    33. myCursor.moveToFirst();
    34. if (myCursor != null) {
    35. if (myCursor.isFirst()) {
    36. EditText eName = (EditText)findViewById(R.id.ed_KfzName);
    37. eName.setText(myCursor.getString(ColumnName));
    38. EditText eModel = (EditText)findViewById(R.id.ed_KfzModel);
    39. eModel.setText(myCursor.getString(ColumnModel));
    40. EditText eBemerkungen = (EditText)findViewById(R.id.ed_KfzBemerkung);
    41. eBemerkungen.setText(myCursor.getString(ColumnBemerkung));
    42. Spinner sKraftstoffarten = (Spinner)findViewById(R.id.cb_KfzTreibstoffArt);
    43. sKraftstoffarten.setSelection(myCursor.getInt(ColumnKraftstoffart), true);
    44. EditText eTankinhalt = (EditText)findViewById(R.id.ed_KfzTankinhalt);
    45. eTankinhalt.setText(myCursor.getString(ColumnTankinhalt));
    46. }
    47. }
    48. }
    49. }
    Alles anzeigen



    Wir erstellen das Menü und fragen erneut ab ob eine _id übergeben wurde oder nicht.
    Wurde eine _id übergeben, steht auf unserem Button "Update" ansonsten "Speichern"

    Java-Quellcode

    1. public boolean onCreateOptionsMenu(Menu menu) {
    2. super.onCreateOptionsMenu(menu);
    3. if(getIntent().hasExtra("id") == true)
    4. {
    5. menu.add(0, MENU_UPDATE_KFZ, 0, R.string.menuUpdate)
    6. .setShortcut('1', 's')
    7. .setIcon(android.R.drawable.ic_menu_save);
    8. }
    9. else
    10. {
    11. menu.add(0, MENU_INSERT_KFZ, 0, R.string.menuInsert)
    12. .setShortcut('1', 's')
    13. .setIcon(android.R.drawable.ic_menu_save);
    14. }
    15. return true;
    16. }
    Alles anzeigen




    Java-Quellcode

    1. public boolean onOptionsItemSelected(MenuItem item){
    2. switch (item.getItemId()) {
    3. case MENU_INSERT_KFZ:
    4. EditText KfzName = (EditText)findViewById(R.id.ed_KfzName);
    5. EditText KfzModel = (EditText)findViewById(R.id.ed_KfzModel);
    6. EditText KfzBemerkungen = (EditText)findViewById(R.id.ed_KfzBemerkung);
    7. Spinner KfzKraftstoffart = (Spinner)findViewById(R.id.cb_KfzTreibstoffArt);
    8. EditText KfzTankinhalt = (EditText)findViewById(R.id.ed_KfzTankinhalt);
    9. int i = KfzKraftstoffart.getSelectedItemPosition();
    10. if(KfzName.length()!=0)
    11. {
    12. myDB = this.openOrCreateDatabase(TankPro2.MY_DB_NAME,
    13. MODE_PRIVATE, null);
    14. //KFZ-Daten updaten (UPDATE)
    15. if(getIntent().hasExtra("id") == true)
    16. {
    17. long l = getIntent().getExtras().getLong("id");
    18. myDB.execSQL("UPDATE "+TankPro2.MY_DB_TABLE+" SET "+
    19. "name = '"+KfzName.getText().toString()+"', "+
    20. "model = '"+KfzModel.getText().toString()+"', "+
    21. "bemerkungen ='"+KfzBemerkungen.getText().toString()+"', "+
    22. "kraftstoffart ='"+i+"', "+
    23. "tankinhalt = '"+KfzTankinhalt.getText().toString()+"' "+
    24. "WHERE _id = "+l+";");
    25. }
    26. //Neues KFZ in Datenbank speichern (INSERT)
    27. else
    28. {
    29. myDB.execSQL("INSERT INTO "+TankPro2.MY_DB_TABLE+"
    30. (name,
    31. model,
    32. bemerkungen,
    33. kraftstoffart,
    34. tankinhalt) "
    35. +"VALUES ('"+KfzName.getText().toString()+"',"+
    36. "'"+KfzModel.getText().toString()+"',"+
    37. "'"+KfzBemerkungen.getText().toString()+"',"+
    38. "'"+i+"',"+"'"+
    39. KfzTankinhalt.getText().toString()+"');");
    40. }
    41. finish();
    42. return true;
    43. }
    44. else
    45. {
    46. Toast toast = Toast.makeText(this, "Bitte geben Sie einen Namen für das Fahrzeug ein!",
    47. Toast.LENGTH_SHORT);
    48. toast.show();
    49. }
    50. }
    51. return false;
    52. }
    53. }
    Alles anzeigen
    HTC-Magic white
    Development: Eclipse Ganymede + Android SDK 1.5
    Linux Mint 6
  • hi ensacon,
    wollte mich für deinen Beitrag bedanken.
    Es sind viele Sachen die du neben SQLlite noch abdeckst (layoutWidgets,Adapter...) ;)
    Leider kann ich keinen Link zu den Anhängen finden. (Da ich seit heute hier angemeldet bin, weiss ich nun
    nicht ob ich was übersehen hab.) Vielleicht kannst du mich aufklären, was (Anhänge) wo zu finden ist.
    Danke schon mal im Voraus
  • Erstellen der DB scheitert

    Jo, ansich ein schönes und leicht verständliches Tutorial. Allerdings scheitert es bei mir schon beim Erstellen der Datenbank mit

    Java-Quellcode

    1. myDB = this.openOrCreateDatabase(MY_DB_NAME, MODE_PRIVATE, null);


    MY_DB_NAME ist korrekt definiert und myDB initialisiert und die sqlite Klasse natürlich eingebunden.

    Habe danach versucht Tabellen anzulegen und Datensätze zu schreiben, aber die Activity ist sofort abgestürzt. Die IDE hat beim Compilieren keinen Fehler gezeigt und der ADB Debugger hat auch nicht ausgespuckt dass mir weiter geholfen hätte.
    Nachdem ich alle Anweisungen in Try-Catch Blöcke gepackt habe, stellte sich heraus, dass schon das Erstellen der DB fehl schlägt.

    Hat jemand eine Idee?
  • Benutzer-Avatarbild

    Gravedigger schrieb:

    Jo, ansich ein schönes und leicht verständliches Tutorial. Allerdings scheitert es bei mir schon beim Erstellen der Datenbank mit

    Java-Quellcode

    1. myDB = this.openOrCreateDatabase(MY_DB_NAME, MODE_PRIVATE, null);


    MY_DB_NAME ist korrekt definiert und myDB initialisiert und die sqlite Klasse natürlich eingebunden.

    Habe danach versucht Tabellen anzulegen und Datensätze zu schreiben, aber die Activity ist sofort abgestürzt. Die IDE hat beim Compilieren keinen Fehler gezeigt und der ADB Debugger hat auch nicht ausgespuckt dass mir weiter geholfen hätte.
    Nachdem ich alle Anweisungen in Try-Catch Blöcke gepackt habe, stellte sich heraus, dass schon das Erstellen der DB fehl schlägt.

    Hat jemand eine Idee?


    Ist es möglich, dass MY_DB_NAME ein Member einer Klasse ist? Dann musst du den Klassenbezeichner vor MY_DB_NAME schreiben.

    wfg Jon
  • Das hilft leider auch nicht. Habe sogar versucht den DB Namen direkt als String in den Befehl zu schreiben. Aber sobald der Befehl aufgerufen wird, stürzt das Programm ab, bzw. wird vom Catch abgefangen. Ich weiß nicht mehr weiter, im Prinzip ist der Befehl doch viel zu einfach um was falsch machen zu können. Hab mich wochenlang mit allen GUI-Elementen und Android-Eigenschaften vertraut gemacht und jetzt kann ich mit meinem Projekt nicht loslegen weil ich die Datenbank nicht initialisiert kriege...!?

    Gibt es vielleicht irgendwo die Möglichkeit sich eine Fehlermeldung ausgeben zu lassen? Eine log-Datei von SQLite oder irgendetwas das mir sagen könnte was schief läuft?

    Java-Quellcode

    1. package org.me.ganjatest;
    2. import android.database.sqlite.*;
    3. import android.app.Activity;
    4. import android.database.Cursor;
    5. import android.os.Bundle;
    6. import android.widget.SimpleCursorAdapter;
    7. import android.widget.Toast;
    8. public class dbLite extends Activity{
    9. private SQLiteDatabase myDB = null;
    10. private gmDebug deb = new gmDebug();
    11. final static String MY_DB_NAME = "ganjaDB";
    12. public dbLite()
    13. {
    14. deb.out("dbLite", "Konstruktor wird ausgeführt");
    15. onCreateDBAndDBTabled();
    16. }
    17. private void onCreateDBAndDBTabled()
    18. {
    19. try
    20. {
    21. deb.out("dbLite", "versuche Datenbank zu öffnen");
    22. myDB = this.openOrCreateDatabase(dbLite.MY_DB_NAME, MODE_PRIVATE, null);
    23. }
    24. catch (Exception e)
    25. {
    26. deb.out("dbLite", "offnen der Datenbank fehlgeschlagen");
    27. }
    28. }
    29. }
    Alles anzeigen
  • Hallo!

    Ich habe das Problem auch gehabt und 5 Stunden gegoogelt.
    Mit Hilfe vom catlog (in Eclipse) habe ich herausgefunden, dass die DB nicht geöffnet werden konnte (sqlite Error 14).
    Daraufhin habe ich den Fehler gesucht und das Ergebnis ist, dass "MODE_PRIVATE" in "Context.MODE_PRIVATE" geändert werden muss (import nicht vergessen).
    Dann ging es wie von Geisterhand...

    So sieht es bei mir aus:

    Quellcode

    1. myDB = this.openOrCreateDatabase(DBNAME, Context.MODE_PRIVATE, null);


    Kann es sein, dass es an Android 2.2 liegt und es bei vorherigen Versionen auch ohne Context funktionierte?
  • ich finde du hast die verwendung von sqlite in java sehr gut und verstänlich erklärt. ich habe schon länger nach so einem tutorial gesucht. jetzt hab ich mich hier durchgearbeitet und den code abgetippt und versucht zu verstehn und hätte jetzt sehr gern die notwenigen dateien damit ich die app auch testen kann, also könnte mir bitte jemand sagen wo dieser anhang sein soll. ich möchte das ganze nicht um sonst gemacht haben. wenn ich den anhang bekomme gibts 5 sterne!
  • Hi kaetzchenfg,

    bin zwar kein Mod aber normalerweise findest du sowas im Beitrag.
    Da aber dort nichts zu finden ist sieht es schlecht aus.

    Du kannst natürlich versuchen "ensacom" an zuschreiben aber da der Beitrag 3 Jahre alte ist und so wie es aussieht er seinen letzten Post auch in dieser Zeit hatte wirst du wahrscheinlich keine Antwort bekommen.

    Mfg Titus
  • Der Anhang existiert wohl nicht mehr :(
    Aber steht ja viel im Post.
    Außerdem sollte man heutzutage mit einem DatabaseHelper arbeiten...
    Es gibt dazu einige Tutorials im Netz. ;)
    Leider finde ich nicht das, was ich damals benutzt habe. Aber Google hilft dir bestimmt weiter :)
    MfG,
    Christopher

    Eine gewisses Maß an Freundlichkeit kann man auch von Menschen im Internet erwarten.
    Das Forum basiert komplett auf der Freiwilligkeit ihrer Nutzer und diese sollen sich wohlfühlen! Daher seid bitte freundlich. Danke.

    Ich bitte von Anfragen per PN abzusehen!