Как избежать специальных символов, таких как 'в sqlite в Android

36

У меня есть функция, которая выполняет запрос в таблице в базе данных SQLite. Я объявляю константу: public static final String CANADA_HISTORY = "Canada History";. Это сохраняется в переменной String, скажем, difficulty,

У меня есть один запрос:

Cursor c = mDb.rawQuery("select * from Questions_answers where CHAPTERS = '"+difficulty+"'" , null);

Он выдает исключение возле апострофа.

Выход Logcat:

I/Database( 1170): sqlite returned: error code = 1, msg = near "s": syntax error
D/AndroidRuntime( 1170): Shutting down VM
W/dalvikvm( 1170): threadid=1: thread exiting with uncaught exception (group=0x40015560)
E/AndroidRuntime( 1170): FATAL EXCEPTION: main
E/AndroidRuntime( 1170): android.database.sqlite.SQLiteException: near "s": syntax error: , while compiling: select * from Questions_answers where CHAPTERS  = 'Canada History'

Я также пробовал:

1.  difficulty=difficulty.replaceAll("'","''");
2.  difficulty=difficulty.replaceAll("'","\'");
3.  difficulty = DatabaseUtils.sqlEscapeString(difficulty);

Чтобы добавить к этому, он работает со мной для отдельных слов типа Canada History, я имею в виду без специального символьного слова.

Пожалуйста, дайте мне совет для решения проблемы. Спасибо.

  • 7
    попробуйте использовать selectionArgs , например, для: rawQuery("select * from table where chapters = ?", new String[] { difficulty } );
Теги:
special-characters

9 ответов

24
Лучший ответ

Сначала замените символ этим

difficulty=difficulty.replaceAll("'","\\'");

затем передайте это в вашем запросе

"select * from Questions_answers where CHAPTERS='"+difficulty+"'";

Редактировать :

 q = "select * from Questions_answers where CHAPTERS = ?";
    database.rawQuery(q, new String[] { difficulty});
  • 0
    ты пробовал как вместо =?
  • 1
    Как насчет тире, дефиса "-"?
Показать ещё 1 комментарий
88

Стандарт SQL указывает, что одиночные кавычки в цепочках экранируются путем размещения двух одиночных кавычек в строке. SQL работает как язык программирования Pascal. SQLite следует этому стандарту. Пример:

INSERT INTO xyz VALUES('5 O''clock');

Ссылка: Часто задаваемые вопросы по SQLite

  • 8
    это ужасно Используйте selectionArgs. не пытайтесь дезинфицировать входные данные sql самостоятельно.
  • 0
    @ njzk2 Эй, спасибо за указание. Но было бы лучше, если бы вы добавили подробности о том, «почему это ужасно?». Это помогло бы другим пользователям :). Кстати, я не получил ваши очки здесь, потому что этот ответ был для экранирования специальных символов.
Показать ещё 3 комментария
46

Лучший способ - использовать собственный метод Android, предназначенный именно для этой цели:

DatabaseUtils.sqlEscapeString(String)

Вот документация для него онлайн:

Основным преимуществом использования этого метода, на мой взгляд, является самодокументация из-за явного имени метода.

  • 4
    После использования этой функции у меня возникли проблемы с запросами, поскольку она определенно окружает вашу строку одинарными кавычками, которые затем становятся частью вашей строки, и вы должны соответствующим образом адаптировать свои запросы или использовать другой метод для экранирования строк. Более подробная информация на stackoverflow.com/questions/31334723/…
  • 0
    да, испортил мои запросы тоже (
Показать ещё 1 комментарий
26

Что сработало для меня, было

if (columnvalue.contains("'")) {
    columnvalue = columnvalue.replaceAll("'", "''");
}
  • 1
    Это сработало и для меня. Я также добавил нулевую проверку, прежде чем она станет безопасной. Я не могу поверить, что собственный метод GOOG DatabaseUtils.sqlEscapeString () такой мусор.
  • 0
    String.replaceAll создает шаблон. Я не уверен , что это очень оптимальна только для замены '
Показать ещё 2 комментария
3

вы можете попробовать Cursor c = mDb.rawQuery("select * from Questions_answers where CHAPTERS = \""+difficulty+"\"" , null);

2

Это будет работать одинаково:

if (columnValue.contains("'")) 
    columnValue = columnValue.replaceAll("'", "[']");

или

if (columnValue.contains("'")) 
    columnValue = columnValue.replaceAll("'", "\\\'");

но в действительности мы используем следующие символы% и _

1

Что DatabaseUtils.sqlEscapeString(s) по существу делает, заменяет все одинарные кавычки (') двумя одинарными кавычками ('') и добавляет одну одинарную цитату в начале и одну в конце строки.
Поэтому, если вы просто хотите избежать String, эта функция должна работать:

private static String escape(String s) {
    return s != null ? s.replaceAll("\'", "\'\'") : null;
}
0

В соответствии с моим пониманием есть два подхода:

String test = "Android vaersion"     test = test.replace( "'", "' '" );

Этот сценарий абсолютно прекрасен, но я бы определенно предложил использовать следующий подход.

String test = "Android vaersion"     test = test.replaceAll( "'", "\" );

Мы столкнулись с проблемой из-за первого подхода, когда мы пытались обновить и выбрать значение таблицы SQLite с помощью '.

-2

Вам не нужно скрывать \, как? так что это будет replaceAll("'", "\\'") Или я ошибаюсь в этом?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню