Ответ 1
getColumnIndex() чувствителен к регистру:
Название столбца в БД: Правила
cursor.getColumnIndex( " Правила" ) //отлично работает
cursor.getColumnIndex( " правила" )//выдает ошибку, см. описание ошибки
Работая с SQLiteCursor в Android, я узнал, что getColumnIndex() ведет себя с учетом регистра, например:
Пример:
Column Name in DB was: Rules
cursor.getColumnIndex("Rules") //workes fine
cursor.getColumnIndex("rules") //throws error, see the error detail
В документации об этом ничего не сказано, подробности смотритездесь.
LogCat говорит:
java.lang.IllegalStateException: не удалось прочитать строку 0, столбец -1 из CursorWindow. Убедитесь, что курсор инициализирован правильно, прежде чем доступ к данным из него
Меня смущает такое поведение SQLiteCursor, может ли кто-нибудь помочь мне, что это правда ИЛИ я делаю что-то не так? Я могу предоставить код, если требуется.
Благодарю.
getColumnIndex() чувствителен к регистру:
Название столбца в БД: Правила
cursor.getColumnIndex( " Правила" ) //отлично работает
cursor.getColumnIndex( " правила" )//выдает ошибку, см. описание ошибки
Лучший и рекомендуемый подход с использованием SQLite заключается в том, что вы объявляете все имена таблиц и столбцов static
, final
и class
level.. например:
// write table name
public static final String TABLE_MESSAGE = "messages";
// and column name accordingly
public static final String COLUMN_ID = "_id";
public static final String COLUMN_MESSAGE = "message";
поэтому преимущество этого подхода состоит в том, что вам не нужно запоминать орфографию и случай и т.д. имен таблиц и столбцов.
когда вы обращаетесь к любой таблице или столбцу, вы просто используете эти статические переменные, например:
// TABLE creation sql statement
private static final String TABLE_CREATE = "create table "
+ TABLE_MESSAGE + "( " + COLUMN_ID
+ " integer primary key autoincrement, " + COLUMN_MESSAGE
+ " text not null);";
при запросе:
database.query(TABLE_MESSAGE, new String[]{COLUMN_ID,COLUMN_MESSAGE}, null, null, null, null, null);
или он может использоваться в курсоре
int index = cursor.getColumnIndex(COLUMN_MESSAGE);
это поможет вам избежать таких конфликтов чувствительности к регистру и орфографических ошибок.:)
Другим способом будет запрос самой базы данных для правильного имени с помощью PRAGMA table_info
, поэтому я написал метод для всего этого:
public class database {
private SQLiteDatabase mainDB = null;
private boolean CreateOrOpenDB() {
try {
if (mainDB == null || !mainDB.isOpen()) {
mainDB = Context.openOrCreateDatabase("mainDB", SQLiteDatabase.CREATE_IF_NECESSARY, null);
}
} catch (SQLiteException e) {
return false;
}
return true;
}
private String GetTrueColumnName(String TableName, String column) {
String TrueColName = "";
if (CreateOrOpenDB()) {
try {
Cursor c = mainDB.rawQuery("PRAGMA table_info(" + TableName + ");", null);
if (c != null) {
if (c.moveToFirst()) {
do {
String dbcolumn = c.getString(c.getColumnIndex("name"));
if (column.toLowerCase().equals(dbcolumn.toLowerCase())) {
TrueColName = dbcolumn;
break;
}
} while (c.moveToNext());
}
c.close();
}
mainDB.close();
} catch (Exception e) {
}
}
return TrueColName;
}
}
тогда вам нужно всего лишь:
String CorrectName = GetTrueColumnName(TableName, "RuLeS");
и да, я знаю, что в базе данных будет сложно. Но он работает и стабилен.
return readableDatabase
.query(
ProductosContract.ProductosEntry.TABLE_NAME,
ProductosContract.ProductosEntry.ALL_COLUMNS_NAME_ALIAS, null, null, null, null, null
)
Вы можете указать столбцы для извлечения, в этом параметре добавьте псевдоним имени столбца в нижний регистр, например (Kotlin):
arrayOf("name as 'name'")
Таким образом, вы всегда будете получать строчные буквы. Используйте нижний регистр или тот, который вы предпочитаете, он будет работать.