Usuwanie wiersza w SQLite w systemie Android

102

To może być głupie pytanie, ale jestem nowy w SQLite i nie mogę tego zrozumieć. Mam 1 tabeli zawierającej kolumny KEY_ROWID, KEY_NAME, KAY_LATITUDE, i KEY_LONGITUDE. Chcę, aby użytkownik mógł wybrać jedną i usunąć ją; Czy ktoś może mi wskazać kierunek, w którym powinienem zacząć? Moje pytanie dotyczy faktycznego usunięcia wiersza, podając tylko jego nazwę.

Odpowiedni kod:

public class BeaconDatabase {

    public static final String KEY_ROWID = "_id";
    public static final String KEY_NAME = "beacon_name";
    public static final String KEY_LATITUDE = "beacon_lat";
    public static final String KEY_LONGITUDE = "beacon_lon";

    private static final String DATABASE_NAME ="BeaconDatabase";
    private static final String DATABASE_TABLE ="beaconTable";
    private static final int DATABASE_VERSION = 1;

    private DbHelper helper;
    private final Context context;
    private SQLiteDatabase db;

    public BeaconDatabase(Context context) {
        this.context = context;
    }

    public BeaconDatabase open() {
        helper = new DbHelper(this.context);
        db = helper.getWritableDatabase();
        return this;
    }

    public void close() {
        helper.close();
    }

    public long createEntry(String name, Double lat, Double lon) {
        ContentValues cv = new ContentValues();
        cv.put(KEY_NAME, name);
        cv.put(KEY_LATITUDE, lat);
        cv.put(KEY_LONGITUDE, lon);
        return db.insert(DATABASE_TABLE, null, cv);
    }

    public void deleteEntry(long row) {

              // Deletes a row given its rowId, but I want to be able to pass
              // in the name of the KEY_NAME and have it delete that row.
              //db.delete(DATABASE_TABLE, KEY_ROWID + "=" + row, null);
    }

    public String getData() {
        String[] columns = { KEY_ROWID, KEY_NAME, KEY_LATITUDE, KEY_LONGITUDE };
        Cursor cursor = db.query(DATABASE_TABLE, columns, null, null, null, null, null);
        String result = "";

        int iRow = cursor.getColumnIndex(KEY_ROWID);
        int iName = cursor.getColumnIndex(KEY_NAME);
        int iLat = cursor.getColumnIndex(KEY_LATITUDE);
        int iLon = cursor.getColumnIndex(KEY_LONGITUDE);

        for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
            result += cursor.getString(iRow) + ": " + cursor.getString(iName) + " - " + cursor.getDouble(iLat) + " latitude " + cursor.getDouble(iLon) + " longitude\n";
        }

        return result;

    }

    private static class DbHelper extends SQLiteOpenHelper {

        public DbHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL("CREATE TABLE " +  DATABASE_TABLE + " (" + 
                    KEY_ROWID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
                    KEY_NAME + " TEXT NOT NULL, " +
                    KEY_LATITUDE + " DOUBLE, " +
                    KEY_LONGITUDE + " DOUBLE);"
            );
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE);
            onCreate(db);
        }
    }
}
roboguy12
źródło
idź z odpowiedzią @iDroid ... jak to będzie działać dla mnie. Dzięki iDroid.

Odpowiedzi:

183

Możesz spróbować tak:

 //---deletes a particular title---
public boolean deleteTitle(String name) 
{
    return db.delete(DATABASE_TABLE, KEY_NAME + "=" + name, null) > 0;
}

lub

public boolean deleteTitle(String name) 
{
    return db.delete(DATABASE_TABLE, KEY_NAME + "=?", new String[]{name}) > 0;
}
Shreyash Mahajan
źródło
61
Odpowiedź Vijaya jest prawidłowa, ponieważ to rozwiązanie umożliwia wykonanie iniekcji SQL, która jest wyciekiem bezpieczeństwa. Na przykład: użyj wartości argumentu nazwa: name = "TRUE; <any SQL command>;"=> „dowolne polecenie SQL” zostanie wykonane. Oczywiście nie stanowi to problemu, jeśli nie ma GUI dla tej funkcji.
bdevay
@bdevay Moja odpowiedź dotyczy zadania w tle, które wykonaliśmy za pomocą zapytania. Więc to nie jest związane z interfejsem użytkownika. Musisz tylko podawać informacje tak dynamicznie, że nie ma potrzeby zabezpieczenia. Jeśli zastosujesz się do odpowiedzi vijaya i ktoś zajmie się inżynierią wsteczną, możesz uzyskać informacje o tabeli w bazie danych i polu, które porównujesz. które robię bezpośrednio w zapytaniu, więc nie ma szans, żeby to pora.
Shreyash Mahajan
@iDroid Explorer: oczywiście, jeśli nie ma danych wejściowych użytkownika lub innego rodzaju możliwości manipulacji zapytaniami zewnętrznymi, ryzyko bezpieczeństwa nie jest większe niż w przypadku innego rozwiązania. Kontynuuj w następnym komentarzu ...
bdevay
1
... Ale nie zgadzam się z częścią twojego komentarza dotyczącą inżynierii wstecznej. Musisz gdzieś i jakoś zdefiniować swoje zapytanie, co oznacza, że ​​inżynieria wsteczna jest zawsze możliwym wyciekiem bezpieczeństwa (nawet w przypadku twojego rozwiązania), szczególnie w Javie, nawet jeśli źródło jest zaciemnione. Może tylko bardziej wydłużyć czas hakowania. Z drugiej strony rekomendacja Google używa argumentów wyboru, sprawdź ten artykuł: link
bdevay
Mam na myśli koncepcję nie nadawania wartości statycznej żadnej metodzie ani żadnej zmiennej. To powinno być maksymalnie dynamiczne. Aby było bezpieczniejsze niż podawanie wartości statycznej. W każdym razie to od użytkownika zależy, jak bardzo bezpieczny będzie chciał uczynić swoją aplikację.
Shreyash Mahajan
157

Spróbuj w ten sposób, może znajdziesz rozwiązanie

String table = "beaconTable";
String whereClause = "_id=?";
String[] whereArgs = new String[] { String.valueOf(row) };
db.delete(table, whereClause, whereArgs);
Vijay
źródło
58

lepiej jest też użyć whereargs;

db.delete("tablename","id=? and name=?",new String[]{"1","jack"});

to jest jak użycie tego polecenia:

delete from tablename where id='1' and name ='jack'

a używanie funkcji delete w taki sposób jest dobre, ponieważ usuwa iniekcje sql.

Enakhi
źródło
2
Czy mógłbyś bardziej szczegółowo opisać swoją odpowiedź, dodając więcej opisu rozwiązania, które oferujesz?
abarisone
1
Myślę, że warto skorzystać z whereargs.
msysmilu
@Enkahi Czy to jest jak przygotowane instrukcje w SQLite? Używałem już tego rodzaju id=?składni w PHP i wygląda to bardzo podobnie.
GeekWithGlasses
17

Dopóki nie zrozumiem twojego pytania, chcesz postawić dwa warunki, aby wybrać wiersz do usunięcia. W tym celu musisz zrobić:

public void deleteEntry(long row,String key_name) {

      db.delete(DATABASE_TABLE, KEY_ROWID + "=" + row + " and " + KEY_NAME + "=" + key_name, null);

      /*if you just have key_name to select a row,you can ignore passing rowid(here-row) and use:

      db.delete(DATABASE_TABLE, KEY_NAME + "=" + key_name, null);
      */  

}
Hiral Vadodaria
źródło
13

Wypróbuj ten kod

public void deleteRow(String value)
{
SQLiteDatabase db = this.getWritableDatabase();       
db.execSQL("DELETE FROM " + TABLE_NAME+ " WHERE "+COlUMN_NAME+"='"+value+"'");
db.close();
}
Harman Khera
źródło
Jak mam to nazwać, gdy chcę usunąć? db.deleteRow ();
Phares
możemy to nazwać, przekazując wartość jako parametr, który chcesz usunąć. Zadzwoń jako db.deleteRow ("nazwa");
Harman Khera
8

Wypróbuj ten kod ...

private static final String mname = "'USERNAME'";
public void deleteContact()
{
    db.delete(TABLE_CONTACTS, KEY_NAME + "=" + mname, null);
}
Giridharan
źródło
3

jeśli używasz SQLiteDatabase, istnieje metoda usuwania

Definicja usunięcia

int delete (String table, String whereClause, String[] whereArgs)

Przykładowe wdrożenie

Teraz możemy napisać metodę o nazwie delete z argumentem jako nazwą

public void delete(String value) {
    db.delete(DATABASE_TABLE, KEY_NAME + "=?", new String[]{String.valueOf(value)});
}

jeśli chcesz usunąć wszystkie rekordy, po prostu przekaż null do powyższej metody,

public void delete() {
    db.delete(DATABASE_TABLE, null, null);
}

Źródło informacji

Jayakrishnan
źródło
Jeśli wartość ciągu jest dołączona do klucza obcego, to ??
Harsh Bhavsar
2

Chłopaki, to jest ogólna metoda, której możesz użyć dla wszystkich swoich tabel, zadziałała idealnie w moim przypadku.

public void deleteRowFromTable(String tableName, String columnName, String keyValue) {
    String whereClause = columnName + "=?";
    String[] whereArgs = new String[]{String.valueOf(keyValue)};
    yourDatabase.delete(tableName, whereClause, whereArgs);
}
Naveed Ahmad
źródło
String.ValueOf (keyValue) => czy możesz wyjaśnić tę linię?
Anis
1
Nie ma potrzeby String.ValueOf (keyValue), ponieważ keyValue jest już ciągiem. w innych przypadkach używamy tego whereArgs Array do identyfikacji wartości nazwy kolumny.
Naveed Ahmad
2

Aby usunąć wiersze z tabeli, musisz podać kryteria wyboru, które identyfikują wiersze w delete()metodzie. Mechanizm działa tak samo, jak argumenty wyboru query()metody. Dzieli specyfikację selekcji na klauzulę selekcyjną (klauzula gdzie) i argumenty selekcji.

    SQLiteDatabase db  = this.getWritableDatabase();
     // Define 'where' part of query.
    String selection = Contract.COLUMN_COMPANY_ID + " =?  and "
                       + Contract.CLOUMN_TYPE +" =? ";
   // Specify arguments in placeholder order.
    String[] selectionArgs = { cid,mode };
    // Issue SQL statement.
    int deletedRows = db.delete(Contract.TABLE_NAME, 
                       selection, selectionArgs);
    return deletedRows;// no.of rows deleted.

Wartość zwracana dla delete()metody wskazuje liczbę wierszy, które zostały usunięte z bazy danych.

Baran
źródło
Chociaż ten kod może odpowiedzieć na pytanie, zapewnia dodatkowy kontekst dotyczący tego, dlaczego i / lub jak ten kod odpowiada, poprawia jego długoterminową wartość.
Thomas Flinkow
1

Chłopaki, jeśli powyższe rozwiązania nie działają dla ciebie, wypróbuj to również, ponieważ zadziałało dla mnie.

public boolean deleteRow(String name) 
{
    return db.delete(DATABASE_TABLE, KEY_NAME + "='" + name +"' ;", null) > 0;
}
aman003
źródło
1

Działa świetnie!

public void deleteNewMelk(String melkCode) {
    getWritableDatabase().delete(your_table, your_column +"=?", new String[]{melkCode});
}
Uwaga Hadi
źródło
0

Spróbuj tego:

public void deleteEntry(long rowId) {
    database.delete(DATABASE_TABLE , KEY_ROWID 
        + " = " + rowId, null);}
Nadhir Titaouine
źródło
0
public boolean deleteRow(long l) {
    String where = "ID" + "=" + l;
    return db.delete(TABLE_COUNTRY, where, null) != 0;
}
babiro
źródło
0

Możesz zrobić coś takiego, udostępniając mój działający fragment kodu

Upewnij się, że zapytanie jest takie

DELETE FROM tableName WHERE KEY__NAME = 'parameterToMatch'

public void removeSingleFeedback(InputFeedback itemToDelete) {
            //Open the database
            SQLiteDatabase database = this.getWritableDatabase();

            //Execute sql query to remove from database
            //NOTE: When removing by String in SQL, value must be enclosed with ''
            database.execSQL("DELETE FROM " + TABLE_FEEDBACKS + " WHERE "
                    + KEY_CUSTMER_NAME + "= '" + itemToDelete.getStrCustName() + "'" +
                    " AND " + KEY_DESIGNATION + "= '" + itemToDelete.getStrCustDesignation() + "'" +
                    " AND " + KEY_EMAIL + "= '" + itemToDelete.getStrCustEmail() + "'" +
                    " AND " + KEY_CONTACT_NO + "= '" + itemToDelete.getStrCustContactNo() + "'" +
                    " AND " + KEY_MOBILE_NO + "= '" + itemToDelete.getStrCustMobile() + "'" +
                    " AND " + KEY_CLUSTER_NAME + "= '" + itemToDelete.getStrClusterName() + "'" +
                    " AND " + KEY_PRODUCT_NAME + "= '" + itemToDelete.getStrProductName() + "'" +
                    " AND " + KEY_INSTALL_VERSION + "= '" + itemToDelete.getStrInstalledVersion() + "'" +
                    " AND " + KEY_REQUIREMENTS + "= '" + itemToDelete.getStrRequirements() + "'" +
                    " AND " + KEY_CHALLENGES + "= '" + itemToDelete.getStrChallenges() + "'" +
                    " AND " + KEY_EXPANSION + "= '" + itemToDelete.getStrFutureExpansion() + "'" +
                    " AND " + KEY_COMMENTS + "= '" + itemToDelete.getStrComments() + "'"
            );

            //Close the database
            database.close();
        }
Hitesh Sahu
źródło
0

Wypróbuj poniższy kod-

mSQLiteDatabase = getWritableDatabase();//To delete , database should be writable.
int rowDeleted = mSQLiteDatabase.delete(TABLE_NAME,id + " =?",
                    new String[] {String.valueOf(id)});
mSQLiteDatabase.close();//This is very important once database operation is done.
if(rowDeleted != 0){
    //delete success.
} else {
    //delete failed.
}
Durgesh
źródło
0

Jedynym sposobem, który działał dla mnie, był ten

fun removeCart(mCart: Cart) {
    val db = dbHelper.writableDatabase
    val deleteLineWithThisValue = mCart.f
    db.delete(cons.tableNames[3], Cart.KEY_f + "  LIKE  '%" + deleteLineWithThisValue + "%' ", null)
}


class Cart {
    var a: String? = null
    var b: String? = null
    var c: String? = null
    var d: String? = null
    var e: Int? = null
    var f: String? = null

companion object {
    // Labels Table Columns names
    const val rowIdKey = "_id"
    const val idKey = "id"
    const val KEY_a = "a"
    const val KEY_b = "b"
    const val KEY_c = "c"
    const val KEY_d = "d"
    const val KEY_e = "e"
    const val KEY_f = "f"
   }
}

object cons {
    val tableNames = arrayOf(
            /*0*/ "shoes",
            /*1*/ "hats",
            /*2*/ "shirt",
            /*3*/ "car"
         )
 }
AllanRibas
źródło