Удалить строку SQLite с предложением where с несколькими предложениями

Я искал вокруг и не смог найти решение или рабочий пример, так что вот.

Я настроил базу данных SQLite, которая имеет пять столбцов с разными полями, которые эффективно создают список для пользователя. В списке будет несколько одинаковых значений, за исключением ROWID, для которого установлено автоматическое увеличение.

Ни пользователь, ни программа не будут знать ROWID после того, как значение будет введено в базу данных, поэтому я хочу, чтобы пользователь мог удалить одну строку, если она содержит все четыре других поля.

Мой код выглядит так:

Database
            .delete(DATABASE_TABLE,
                    "KEY_DATE='date' AND KEY_GRADE='style2' AND KEY_STYLE='style' AND KEY_PUMPLEVEL='pumpLevel'",
                    null);

Но это не удаляет никаких значений. Я почти уверен, что виноват синтаксис этой команды.

Как отформатировать предложение where для команды удаления с несколькими предложениями where?

Решение снизу:

ourDatabase.delete(DATABASE_TABLE, "ROWID = (SELECT Max(ROWID) FROM "
            + DATABASE_TABLE + " WHERE " + "date=? AND grade=? AND "
            + "style=? AND pump_level=?)", new String[] { date, grade,
            style, pumpLevel });

person Gareth Bowen    schedule 28.08.2012    source источник


Ответы (2)


У меня такое ощущение, что KEY_DATE, KEY_GRADE и т. д. – это имена переменных Java, а не ваши настоящие имена столбцов. Попробуйте изменить свой код на это:

.delete(DATABASE_TABLE,
        KEY_DATE + "='date' AND " + KEY_GRADE + "='style2' AND " +
        KEY_STYLE + "='style' AND " + KEY_PUMPLEVEL + "='pumpLevel'",
        null);

Также я предполагаю, что 'date', 'style' и т. д. хранятся в локальных переменных, вы должны использовать параметр whereArgs для проецирования себя из Атаки с внедрением SQL:

.delete(DATABASE_TABLE,
        KEY_DATE + "=? AND " + KEY_GRADE + "=? AND " +
        KEY_STYLE + "=? AND " + KEY_PUMPLEVEL + "=?",
        new String[] {date, grade, style, pumpLevel});

(где date = "date", grade = "style2" и т. д.)


Добавлено из комментариев

Чтобы удалить последнюю строку, используйте это:

.delete(DATABASE_TABLE,
        "ROWID = (SELECT Max(ROWID) FROM " + DATABASE_TABLE + ")",
        null);

Чтобы удалить последнюю совпадающую строку, попробуйте следующее:

.delete(DATABASE_TABLE,
        "ROWID = (SELECT Max(ROWID) FROM " + DATABASE_TABLE + " WHERE " +
            "KEY_DATE='date' AND KEY_GRADE='style2' AND " +
            "KEY_STYLE='style' AND KEY_PUMPLEVEL='pumpLevel')",
        null);

Но посмотрите мою вторую заметку об атаках с помощью SQL-инъекций для защиты ваших данных.

person Sam    schedule 28.08.2012
comment
Извините, я понимаю, что задал здесь идиотский вопрос. Строки идентифицируются только автоматически увеличивающимся ROWID. Что я действительно хочу сделать, так это удалить самый последний ROWID, который содержит поля, соответствующие значениям, переданным в качестве контекста. У вас есть предложение? - person Gareth Bowen; 28.08.2012
comment
Я все еще не уверен в вашем точном вопросе... Но если у вас есть несколько строк с KEY_DATE = 'date' и т. д. и вы хотите удалить последнюю совпадающую строку: вы можете объединить два моих последних предложения. - person Sam; 28.08.2012
comment
Оно работает. Спасибо. Если не сложно, можете ли вы объяснить, как это работает, поскольку я не понимаю, как он узнает, какие значения искать. - person Gareth Bowen; 28.08.2012
comment
Конечно, SELECT Max(ROWID) возвращает самое высокое значение для ROWID, которое является последней добавленной строкой, поскольку вы используете ключ автоинкремента. Так что на самом деле у вас есть две команды, которые происходят: SELECT... находит наибольшее ROWID и передает это значение вашей команде .delete(...). Ознакомьтесь с этим руководством, где подробно описаны различные функции SQL, такие как Count(), Max (), Мин() и т. д. - person Sam; 28.08.2012
comment
PS Пожалуйста, нажмите на галочку в верхнем левом углу моего ответа, чтобы отметить свой вопрос как решенный. - person Sam; 28.08.2012
comment
Хм, я только что понял, что этот код удаляет последнюю запись независимо от содержимого столбцов. Как я могу убедиться, что он удаляет строку только в том случае, если значение столбцов соответствует значениям из переданного контекста? - person Gareth Bowen; 28.08.2012
comment
Я объединил ответы для вас. Видите, как запрос SELECT использует предложение WHERE для поиска Max(ROWID? - person Sam; 28.08.2012
comment
Спасибо, Сэм, я, наконец, решил эту проблему, объединив информацию в следующий код: ourDatabase.delete(DATABASE_TABLE, "ROWID = (SELECT Max(ROWID) FROM " + DATABASE_TABLE + " WHERE " + "date=? AND grade=? AND " + "style=? AND pump_level=?)", new String[] { date, grade, style, pumpLevel }); Спасибо за помощь. - person Gareth Bowen; 29.08.2012

Вы должны использовать:

Database.delete(DATABASE_TABLE,
                "KEY_DATE=? AND KEY_GRADE = ? AND KEY_STYLE = ? AND KEY_PUMPLEVEL = ?",
                 new String[]{"date", "style2", "style", "pumpLevel"});

что упрощает экранирование значений.

person Diego Torres Milano    schedule 28.08.2012
comment
Это работает почти идеально. По какой-то причине мне приходится использовать значение String, которое я связал с ключом. т.е. вместо KEY_DATE я использую date. К сожалению, при этом удаляются все значения, соответствующие критериям даты, класса, стиля и уровня насоса. Я хочу удалить только одно из этих значений и оставить остальные. Можно ли этот код адаптировать для этого? - person Gareth Bowen; 29.08.2012
comment
Вы должны удалять строки из таблицы, используя первичный ключ, который уникален, и поэтому соответствует только одна строка. - person Diego Torres Milano; 29.08.2012
comment
Извините за сумбур, но как мне найти rowid для строк, которые соответствуют четырем значениям, которые я ищу? - person Gareth Bowen; 29.08.2012
comment
Вопрос, который вы должны задать себе, заключается в том, почему вы вставляете строки, которые отличаются только своим идентификатором строки (если это то, что вы делаете). - person Diego Torres Milano; 29.08.2012