SQLite Eintrag löschen mit limit

  • 8 Antworten
  • Letztes Antwortdatum
K

KäseSahne

Neues Mitglied
0
Hallo android-hilfe,

mal wieder brauche ich eure Hilfe. Ich versuche mich gerade an der Entwicklung einer App. In groben Zügen soll sie folgendes machen:

  • Es gibt verschiedene Objekte. In meinem Fall Autos (rote, grüne, gelbe,...)
  • Jedes Objekt hat eine ID. Also z.B. das rote Auto hat die ID 1, das grüne die ID 2, usw.
  • Auf meinem Smartphone habe ich eine SQLite Tabelle erzeugt, die folgende Spalten hat: AutoID und GesehenDatum
  • Wenn ich jetzt ein Auto gesehen habe, wird die ID und das Datum, an dem ich es gesehen habe, per Knopfdruck in die Tabelle eingetragen.
  • Ein weiterer Knopf soll dafür zuständig sein, EIN Auto an einem bestimmten Datum aus der DB zu löschen. Z.B. ein rotes Auto, das ich am 10.11.2012 gesehen habe.
Mit dem Hinzufügen der Autos habe ich keine Probleme, das funktioniert soweit. Mein Problem ist aber, dass ich beim Löschen mit dem Befehl
Code:
db.execSQL("delete from Autotabelle where AutoID=" + autoid + " and GesehenDatum=" + datum);
z.B. alle roten Autos mit dem gleichen Datum lösche.

Daraufhin habe ich mich auf die Suche nach einer Lösung gemacht. Dabei ist das rausgekommen:
Code:
db.execSQL("delete from Autotabelle where AutoID=" + autoid + " and GesehenDatum=" + datum + " limit 1");
Die App fliegt jedoch mit diesem Fehler ab:
Failure 1 (near "limit": syntax error) on 0x182858 when preparing 'delete from Autotabelle where AutoID= 345 and GesehenDatum= 20121110 limit 1;'
Im Internet gibt es viele Einträge dazu. Die einen sagen, dass es kein limit-Befehl bei Android SQLite gibt, die anderen behaupten, dass es funktionieren müsste. Leider hat mir das alles nicht weitergeholfen.


Hättet ihr vlt. eine Idee bzw. könntet mir auf die Sprünge helfen?


Vielen Dank im Voraus!
 
Danke für deine Antwort. Genau über den Eintrag bin ich auf meiner Suche auch gestoßen. Leider funktioniert es bei mir nicht wirklich. Es ist zwar möglich, nur ein Objekt zu löschen, aber danach kann ich nichts mehr löschen.

Hier mal die Codeschnipsel, die ich verändert habe:
Tabelle erstellen:
Code:
db.execSQL("create table if not exists Autotabelle(_id integer primary key, AutoID numeric, GesehenDatum numeric);");

Einen Eintrag einfügen:
Code:
db.execSQL("insert into Autotabelle(AutoID, GesehenDatum) Values (" + autoid + ", '" + datum);

Einen Eintrag löschen:
Code:
db.execSQL("DELETE FROM Autotabelle WHERE AutoID=" + autoid + " and GesehenDatum=" + datum + " and _id IN (SELECT _id FROM Autotabelle ORDER BY _id ASC LIMIT 1)");

Irgendwo ist da noch der Wurm drin. Hat vlt. noch jemand Tipps?
 
Der Code zum Löschen scheint ja nun schonmal richtig zu sein. Um dein Problem mit dem "danach kann ich nichts mehr löschen" wäre ein Codebeispiel hierfür ist vielleicht angebracht.

Nur mal so nebenbei: beim Löschen würd ich das "ORDER BY _id ASC" weg lassen. Dir ist ja egal, welche ID der Eintrag hat - somit würdest du dir etwas Rechenleistung einsparen dadurch, dass der nicht erstmal die Ergebnisse aus deinem Select sortiert.
 
Danke, "order by" habe ich jetzt mal gestrichen. Das Problem, das ich momentan habe, kann ich nicht rekonstruieren. Es tritt immer mal wieder auf.
Ich buche ganz normal Objekte in die DB ein. Das läuft. Wenn ich jetzt aber wieder etwas ausbuchen möchte, kann es sein, dass die DB unverändert bleibt. Dann kann ich zum Teil kein anderes Objekt mehr ausbuchen, egal ob rotes, gelbes oder grünes Auto. Manchmal kann ich nach einem Fehlschlag ein anderes Auto ausbuchen und danach funktioniert alles ganz normal.
Wie gesagt, ich kann das Problem noch nicht wirklich rekonstruieren.

Hier mal ein Teil meiner Klassen:

RegistryActivity, die einmalig eine Autotabelle anlegt

Code:
try{
            SQLiteDatabase db = openOrCreateDatabase("CarloggerDB", MODE_PRIVATE, null);            
            db.execSQL("create table if not exists Autotabelle(_id integer primary key, AutoID numeric, GesehenDatum numeric);");            
            db.close();
            Toast toast = Toast.makeText(getApplicationContext(), "Tabelle erfolgreich angelegt", Toast.LENGTH_SHORT);
            toast.show();
        }
        catch(SQLException e){
            Toast toast = Toast.makeText(getApplicationContext(), "Fehler", Toast.LENGTH_SHORT);
            toast.show();
        }    
        /*Weiterleiten in Hauptmenue*/        
        Intent myIntent = new Intent(RegistrationActivity.this, HauptmenueActivity.class);
        RegistrationActivity.this.startActivity(myIntent);
BookingActivity, die für das Eintrage bzw. Austragen aus der DB zuständig ist. Die IDs und das Datum werden per QR-Scanner eingelesen. Das Format ist: AutoID_GesehenDatum
Ein Fehler beim Scanner schließe ich eigentlich aus.

Code:
public class BookingActivity extends Activity{
    
    /*RadioButton Einbuchen*/
    RadioButton buttonIn;
    
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.booking);
        
       RadioGroup gr = (RadioGroup)findViewById(R.id.bookingRBGr);        
    }
    
    /*Das ist die Methode, die beim Drücken des Speicherbuttons aufgerufen wird*/
    public void bookingScan(View view){
        IntentIntegrator integrator = new IntentIntegrator(this);
        integrator.initiateScan();
    }
    
    /*wird nach Scan aufgerufen*/
    public void onActivityResult(int requestCode, int resultCode, Intent intent) {
        IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
        /*QR-Code Inhalt*/
        String content = "";        
        buttonIn = (RadioButton)findViewById(R.id.bookingRBin);
        
        /*hier werden die Daten des QR-Codes gespeichert: AutoID_GesehenDatum*/
        String[] productContent = new String[2];
        if (scanResult != null) {
            content = scanResult.getContents();
        }
        else{
            content = "Error"; 
        }
        
        /*content zurstueckeln*/        
        if(!content.equals("Error")){
            StringTokenizer tokenizer = new StringTokenizer(content, "_");
            for(int i = 0; tokenizer.hasMoreTokens(); i++){
                productContent[i] = tokenizer.nextToken();
            }
        }
        
        /*Pruefen, welcher RadioButton angeklickt ist*/
        if(buttonIn.isChecked() == true){
            /*Produkt in Datenbank eintragen*/
            SQLiteDatabase db = openOrCreateDatabase("CarloggerDB", MODE_PRIVATE, null);
            db.execSQL("insert into Autotabelle(AutoID, GesehenDatum)Values (" + productContent[0] + ", " + productContent[1]);        
            db.close();            
            Toast toast = Toast.makeText(getApplicationContext(), content + " eingebucht", Toast.LENGTH_SHORT);
            toast.show();     
        }
        else{
            /*Produkt aus Datenbank austragen*/
            try{
                SQLiteDatabase db = openOrCreateDatabase("CarloggerDB", MODE_PRIVATE, null);
                /*hier wird ein Auto aus der Datenbank geloescht*/
                db.execSQL("DELETE FROM Autotabelle WHERE AutoID=" + productContent[0] + " and GesehenDatum=" + productContent[1] + " and _id IN (SELECT _id FROM Autotabelle LIMIT 1)");                
                //db.execSQL("delete from " + LoginActivity.correctUsr + " where ProdID=" + productContent[0] + " and ProdAblaufdatum=" + productContent[3]);        
                db.close();    
                Toast toast = Toast.makeText(getApplicationContext(), ""+productContent[0] + " " +productContent[1]+ " ausgebucht", Toast.LENGTH_LONG);
                toast.show();
            }
            catch(SQLException e){
                Toast toast = Toast.makeText(getApplicationContext(), "Fehler beim Austragen", Toast.LENGTH_SHORT);
                toast.show();
            }
        }
     }
}
InhaltActivity, die mir den DB-Inhalt anzeigt.

Code:
public class InhaltActivity extends Activity{
    
    /*Zwischenspeicher DB auslesen*/
    ArrayList<String> list;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.inhalt);    
        
        String msg = "";
        
        try{
            /*Datenbankinhalt auslesen und in TextView darstellen*/
            list = new ArrayList<String>();             
            SQLiteDatabase db = openOrCreateDatabase("CarloggerDB", MODE_PRIVATE, null);
            
            Cursor autoid = db.rawQuery("select AutoID from Autotabelle order by GesehenDatum", null); 
            Cursor datum = db.rawQuery("select GesehenDatum from Autotabelle order by GesehenDatum", null);
            Cursor pk = db.rawQuery("select _id from Autotabelle order by GesehenDatum", null);
            
            /*DB durchlaufen*/
            for(int i = 0; i<autoid.getCount(); i++){
                autoid.moveToNext();
                String autoidL = autoid.getString(0);
                datum.moveToNext();
                String datumL = datum.getString(0);
                pk.moveToNext();                        /**/    
                String pkL = pk.getString(0);        /**/
                /*ausgelesenen Inhalt in Zwischenspeicher*/
                list.add(pkL + "\n" + autoidL + "\n" + datumL);
            }              
            ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list);
            /*Zwischenspeicher in ListView uebertragen*/
            ListView lv = (ListView)findViewById(R.id.list);
            lv.setAdapter(adapter);
            db.close();
        }
        catch(Exception e){
            Toast toast = Toast.makeText(getApplicationContext(), "Fehler", Toast.LENGTH_SHORT);
            toast.show();
        }      
    }
}
Ich vermute, dass der Fehler noch immer bei dem Ausbuchenbefehl liegt. Wenn ich den auskommentierten Befehl benutze, der alle Autos löscht, die die gleiche ID und das gleiche Datum haben, funktioniert alles wie es soll.
 
Zuletzt bearbeitet:
Hört sich etwas danach an, dass du irgendwo die Datenbank nicht richtig geschlossen hast.

Was auffällt ist, dass du in der InhaltActivity deine Cursor nicht schließt. Die auch mal per close() schließen.

Dann würde ich deinen try-catch-Block entweder um ein finally erweitern, wo dann die Datenbank erst geschlossen wird, oder im catch-Block prüfen, ob deine Datenbank geschlossen wurde, wenn nicht, dann dort schließen.

EDIT:
Zum Debuggen ist es vllt. auch sinnvoll, dir im Catch-Block nicht nur eine Toast-Nachricht auszugeben, sondern lass dir da mal den Stacktrace ausgeben (per e.printStackTrace()).
 
So, ich habe jetzt mal alle deine Vorschläge umgesetzt, aber leider keine Besserung. Nachdem ich die Datenbank benutzt habe, habe ich sie auch immer geschlossen (überprüft).
Das "Problem" ist, dass keine Exception geworfen wird. Alles läuft fehlerfrei ab. Im LogCat steht auch nichts tolles drin.

Ich habe ein paar Tests gemacht und konnte zufällig wieder einen "Fehler" (keine Exception) provozieren.
Mein Vorgehen war:

  • dreimal hintereinander ein rotes Auto eingebucht (alle gleiches Datum)
  • einmal ein blaues Auto eingebucht(anderes Datum)
  • alle Autos werden richtig in der ListView angezeigt
  • blaues Auto löschen -> Fehlschlag, ist noch in DB enthalten (mehrmals versucht, gleiches Ergebnis)
  • einmal rotes Auto löschen -> Erfolg
  • blaues Auto löschen -> wieder Fehlschlag (mehrmals versucht)
  • rotes Auto löschen -> Erfolg
  • blaues Auto löschen -> Fehlschlag
  • rotes Auto löschen ->Erfolg
  • blaus Auto löschen -> Erfolg
Daraufhin habe ich die App wieder gelöscht und alles neu installiert.
Wieder die Autos in der gleichen Reihenfolge wie oben eingescannt und der Fehler tritt erneut auf. Jetzt habe ich dreimal hintereinander das rote Auto gelöscht. Erst danach konnte ich das blaue löschen.


Bei dieser Reihenfolge tritt der Fehler wohl immer auf. Leider habe ich keine Ahnung, was ich noch versuchen könnte.

Edit:
Ich habe weiter Tests gemacht und konnte den Fehler stark eingrenzen.
Es ist mir nur möglich, die Autos in der Reihenfolge auszubuchen, wie ich sie eingebucht habe. Alles andere schlägt fehl.
Z.B.:

Einbuchen Reihenfolge:

  • 1xrot
  • 1xgrün
  • 1xblau
Ausbuchen Reihenfolge:


  • 1xrot
  • 1xgrün
  • 1xblau

Edit 2:

Kann es sein, dass das mit der ID (Primary Key) zusammenhängt?

Edit 3:
Nach langem Rumprobieren habe ich die Lösung gefunden. Das Problem lag am SQLite Löschbefehl. Ich habe die Where-Bedingung in die Klammer gezogen und bis jetzt funktioniert es.
Hier nochmal der funktionierende Code:
Code:
db.execSQL("DELETE FROM Autotabelle where _id IN (SELECT _id FROM Autotabelle WHERE AutoID=" + autoid + " and GesehenDatum=" + datum + " LIMIT 1)");

Nochmal vielen Dank für deine Hilfestellung, TheNephilim :thumbup:
 
Zuletzt bearbeitet:
Hey, wenn du immer wieder mit der ID die Autos löscht dann kann es nicht gut gehen denn die id müsste eigentlich als AUTO INCREMENT eingetragen sein welches heißt das es um je weiteres Objekt um eins erhöht wird. Du müsstest im Prinzip die ID herausfinden und genau die ID löschen. Oder du addierst einen extra column der das jeweilige Auto bescheibt und dann kannst du mit diesen column auf das einzelne zugreifen und löschen. Vielleicht hilft dir das aweng^^bin verpeilt

MfG
 
Hallo Kollen,

danke für deine Antwort. Ich habe in meiner Tabelle zwei IDs. Einmal die ID, die bei jedem neuen Objekt automatisch hochzählt (bei mir _id genannt) und einmal eine ID, die vom Objekt abhängig ist (AutoID). Z.B. haben bei mir alle roten Autos die AutoID 123, ... Die Bedingung, mit der ich lösche, hängt von der AutoID ab, nicht von der automatischen (_id). Wie ich unter Edit 3 meines letzten Posts geschrieben habe, habe ich das Problem mit Umstellung der delete-Anweisung in den Griff bekommen.

Gruß
 

Ähnliche Themen

P
Antworten
13
Aufrufe
542
Peter18
P
Zurück
Oben Unten