У меня есть функция, которая выполняет запрос в таблице в базе данных 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
, я имею в виду без специального символьного слова.
Пожалуйста, дайте мне совет для решения проблемы. Спасибо.
Сначала замените символ этим
difficulty=difficulty.replaceAll("'","\\'");
затем передайте это в вашем запросе
"select * from Questions_answers where CHAPTERS='"+difficulty+"'";
Редактировать :
q = "select * from Questions_answers where CHAPTERS = ?";
database.rawQuery(q, new String[] { difficulty});
Стандарт SQL указывает, что одиночные кавычки в цепочках экранируются путем размещения двух одиночных кавычек в строке. SQL работает как язык программирования Pascal. SQLite следует этому стандарту. Пример:
INSERT INTO xyz VALUES('5 O''clock');
Лучший способ - использовать собственный метод Android, предназначенный именно для этой цели:
DatabaseUtils.sqlEscapeString(String)
Вот документация для него онлайн:
Основным преимуществом использования этого метода, на мой взгляд, является самодокументация из-за явного имени метода.
Что сработало для меня, было
if (columnvalue.contains("'")) {
columnvalue = columnvalue.replaceAll("'", "''");
}
'
вы можете попробовать Cursor c = mDb.rawQuery("select * from Questions_answers where CHAPTERS = \""+difficulty+"\"" , null);
Это будет работать одинаково:
if (columnValue.contains("'"))
columnValue = columnValue.replaceAll("'", "[']");
или
if (columnValue.contains("'"))
columnValue = columnValue.replaceAll("'", "\\\'");
но в действительности мы используем следующие символы% и _
Что DatabaseUtils.sqlEscapeString(s)
по существу делает, заменяет все одинарные кавычки ('
) двумя одинарными кавычками (''
) и добавляет одну одинарную цитату в начале и одну в конце строки.
Поэтому, если вы просто хотите избежать String, эта функция должна работать:
private static String escape(String s) {
return s != null ? s.replaceAll("\'", "\'\'") : null;
}
В соответствии с моим пониманием есть два подхода:
String test = "Android vaersion" test = test.replace( "'", "' '" );
Этот сценарий абсолютно прекрасен, но я бы определенно предложил использовать следующий подход.
String test = "Android vaersion" test = test.replaceAll( "'", "\" );
Мы столкнулись с проблемой из-за первого подхода, когда мы пытались обновить и выбрать значение таблицы SQLite с помощью '.
Вам не нужно скрывать \, как? так что это будет replaceAll("'", "\\'")
Или я ошибаюсь в этом?
selectionArgs
, например, для:rawQuery("select * from table where chapters = ?", new String[] { difficulty } );