Android - SQLite 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, может ли кто-нибудь помочь мне, что это правда ИЛИ я делаю что-то не так? Я могу предоставить код, если требуется.

Благодарю.

Ответ 1

getColumnIndex() чувствителен к регистру:

Название столбца в БД: Правила

cursor.getColumnIndex( " Правила" ) //отлично работает

cursor.getColumnIndex( " правила" )//выдает ошибку, см. описание ошибки

Ответ 2

Лучший и рекомендуемый подход с использованием 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);

это поможет вам избежать таких конфликтов чувствительности к регистру и орфографических ошибок.:)

Ответ 3

Другим способом будет запрос самой базы данных для правильного имени с помощью 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");

и да, я знаю, что в базе данных будет сложно. Но он работает и стабилен.

Ответ 4

return readableDatabase
            .query(
                ProductosContract.ProductosEntry.TABLE_NAME,
                ProductosContract.ProductosEntry.ALL_COLUMNS_NAME_ALIAS, null, null, null, null, null
            )

Вы можете указать столбцы для извлечения, в этом параметре добавьте псевдоним имени столбца в нижний регистр, например (Kotlin):

arrayOf("name as 'name'")

Таким образом, вы всегда будете получать строчные буквы. Используйте нижний регистр или тот, который вы предпочитаете, он будет работать.