Android SQLite Удалить Arraylist - PullRequest
       11

Android SQLite Удалить Arraylist

1 голос
/ 02 апреля 2019

Я пытаюсь передать ArrayList значений предложению where в операторе удаления в Sqlite для Android. Вот как выглядит мой код:

int delete = dbHelper.delete("MyTable", "field1 IN ?", new String[] {myList.toString()});

Я получаю Sqlite Exception, выдавая

android.database.sqlite.SQLiteException: near "?": syntax error (code 1): , while compiling: DELETE FROM MyTable WHERE field1 IN ?

Должен ли параметр иметь скобки вместо скобок? Или я делаю что-то еще не так.

Ответы [ 2 ]

1 голос
/ 02 апреля 2019

Да, аргументы / значения для предложения IN должны представлять собой список значений в скобках, разделенных запятыми, и дополнительно каждое значение, если не числовое, заключено в одинарные кавычки ( двойные кавычки могутследует использовать, НО они не рекомендуются см. ключевые слова SQLite ).

Однако, что вы действительно делали неправильно

в соответствии с WHERE field1 IN ('A','B','C')

Таким образом, вы можете использовать: -

boolean after_first_string = false;
StringBuffer sb = new StringBuffer("(");
for(String s: mylist) {
    if (after_first_string) {
        sb.append(",");

    }
    after_first_string = true;
    sb.append("'").append(s.replace("'","''")).append("'");
}
sb.append(")");

int delete = dbHelper.delete("MyTable", "field1 IN " + sb.toString(),null);
  • Обратите внимание, что из-за вложенных аргументов для защиты от внедрения SQL передача ('A', 'B', 'C') какодно значение приведет к тому, что оно будет заключено в одинарные кавычки и будет рассматриваться как одно строковое значение.
    • Следовательно, необходимо передать все предложение WHERE ( в данном случае ) в качестве 2-го параметра и, следовательно, 3-го параметра в качестве NULL.
  • Вышеупомянутое, поскольку оно заключает в себе строки, обеспечивает защиту от внедрения SQL.
  • Метод замены используется для двойных кавычек в любой одинарной кавычке в списке строк.

Рабочий пример: -

Используемый код

В этом примере используется базовый помощник по базе данных, который включает метод delete , который передает 3 параметра в удобный метод delete , которыйПредполагается, что он точно повторяет ваш метод delete (как правило, это просто оболочка) в соответствии с: -

public class DBHelper extends SQLiteOpenHelper {

    public static final String DBNAME = "mydb";
    public static final int DBVERSION = 1;

    public static final String TBL_MYTABLE = "mytable";
    public static final String COL_MYTABLE_FIELD1 = "field1";

    SQLiteDatabase mDB;

    public DBHelper(Context context) {
        super(context, DBNAME, null, DBVERSION);
        mDB = this.getWritableDatabase();
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE IF NOT EXISTS " + TBL_MYTABLE + "(" +
                COL_MYTABLE_FIELD1 + " TEXT" +
                ")");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }

    public long insert(String field1) {
        ContentValues cv = new ContentValues();
        cv.put(COL_MYTABLE_FIELD1,field1);
        return mDB.insert(TBL_MYTABLE,null,cv);
    }

    public int delete(String table, String whereclause, String[] whereargs) {
        return mDB.delete(table,whereclause,whereargs);
    }
} 

Активность вызова: -

  1. Создает экземплярпомощник базы данных как dbhelper (репликация того, что будет сделано в вашем коде).
  2. Добавляет несколько строк (удаляя любые существующие строки), а затем использует предложенный метод.
    1. Обратите внимание, что строка с одинарными кавычками демонстрирует потенциальную необходимость удвоения одинарных кавычек для каждой одинарной кавычки, если она существует в данных.
  3. создает предложение IN (включаязаключающие в скобки).
  4. Вызывает метод delete объекта dbhelper.

Регистрация некоторых важных аспектов.Код: -

public class MainActivity extends AppCompatActivity {

    DBHelper dbHelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        dbHelper = new DBHelper(this);
        dbHelper.getWritableDatabase().delete(DBHelper.TBL_MYTABLE,null,null);
        dbHelper.insert("A");
        dbHelper.insert("B");
        dbHelper.insert("C");
        dbHelper.insert("D");
        dbHelper.insert("'");

        ArrayList<String> mylist = new ArrayList<>();
        mylist.add("A");
        mylist.add("B");
        mylist.add("C");
        mylist.add("'");


        //String[] mylist = new String[]{"A","B","D","'"}; //<<<<<< String array works as well

        Log.d("ARRAYTOSTRING",mylist.toString());
        boolean after_first_string = false;
        StringBuffer sb = new StringBuffer("(");
        for(String s: mylist) {
            if (after_first_string) {
                sb.append(",");
            }
            after_first_string = true;
            sb.append("'").append(s.replace("'","''")).append("'");
        }
        sb.append(")");
        Log.d("WHEREINARG", "The WHERE IN clause will use " + sb.toString());

        int delete = dbHelper.delete("MyTable", "field1 IN " + sb.toString(),null);
        Log.d("DELETED","Rows deleted = " + String.valueOf(delete));
    }
}

Результат

04-03 10:33:46.019 1609-1609/? D/ARRAYTOSTRING: [A, B, C, ']
04-03 10:33:46.019 1609-1609/? D/WHEREINARG: The WHERE IN clause will use ('A','B','C','''')
04-03 10:33:46.023 1609-1609/? D/DELETED: Rows deleted = 4

, то есть 4 из 5 строк, как и ожидалось, были удалены.Аргумент WHERE IN во всей его полноте равен ('A', 'B', 'C', '' '')

0 голосов
/ 02 апреля 2019

Добавьте одинарные кавычки в начале и в конце каждого элемента списка:

for (int i = 0; i < myList.size(); i++) {
    myList.set(i, "'" + myList.get(i) + "'");
}

Затем создайте строку через запятую со всеми значениями списка:

String list = TextUtils.join(",", myList)

Вам понадобится этот импорт:

import android.text.TextUtils

, а затем:

String where = "field1 IN (" + list + ")";
int delete = dbHelper.delete("MyTable", where, null);
...