Как я могу использовать этот запрос с методом запроса (SQLiteDatabase.query)? - PullRequest
2 голосов
/ 22 апреля 2019

Задача, которую мне дали, - написать запрос, чтобы вернуть количество потерянных строк.Я достиг этого, но другая задача состоит в том, чтобы затем не использовать метод rawQuery для достижения того же результата, используя метод запроса.

Проблема заключается в том, что я получаю java.lang.IllegalStateException: Недопустимые таблицы

Таблицы, есть 3:

  1. родительская таблица, которая имеет столбец _id и столбец имени
  2. дочерняя таблица, которая имеет столбец _id, столбец имени и дочернюю родительскую ссылкустолбец, представляющий собой целое число, которое ссылается на родительскую таблицу.
  3. таблица друзей, в которой есть столбец _id, столбец имени и столбец friendtochildlink.

SQL для создания иположить строки в таблицы, в том числе некоторые сироты, как

CREATE TABLE parent(_id INTEGER PRIMARY KEY,parentname TEXT);
CREATE TABLE child(_id INTEGER PRIMARY KEY,childname TEXT, childtoparentlink INTEGER);
CREATE TABLE friend(_id INTEGER PRIMARY KEY,friendname TEXT, friendtochildlink INTEGER);
INSERT INTO parent VALUES(null,'Parent A');
INSERT INTO parent VALUES(null,'Parent B');
INSERT INTO child VALUES(null,'Child A',1);
INSERT INTO child VALUES(null,'Child B',2);
INSERT INTO child VALUES(null,'Child X',10); -- orphan
INSERT INTO friend VALUES(null,'Friend A',1);
INSERT INTO friend VALUES(null,'Friend B',2);
INSERT INTO friend VALUES(null,'Friend X',100); -- orphan

Запрос, который работает и дает правильные значения при использовании rawQuery:

SELECT 
    (
        SELECT count() FROM child 
            LEFT JOIN parent ON child.childtoparentlink = parent._id 
        WHERE parent.parentname IS NULL
    ) AS child_mismatches,
    (
        SELECT count() FROM friend 
            LEFT JOIN child ON friend.friendtochildlink = child._id 
        WHERE child.childname IS NULL
    ) AS friend_mismatches
  • Я получаю по два столбца каждыйсо значением 1 (по желанию).

Мой фактический код: -

public ArrayList<String> checkLinkIntegrity() {
    ArrayList<String> return_value = new ArrayList<>();
    String suffix = "_mismatches";
    String child_result_cl = TB_CHILD + suffix;
    String sq_child_mismatches = "(SELECT count() FROM " +
            TB_CHILD +
            " LEFT JOIN " + TB_PARENT +
            " ON " + TB_CHILD + "." + CL_CHILDTOPARENTLINK + " = " +
            TB_PARENT + "." + CL_PARENTID +
            " WHERE " + TB_PARENT + "." + CL_PARENTNAME + " IS NULL)" +
            " AS " + child_result_cl;
    String friend_result_cl = TB_FRIEND + suffix;
    String sq_friend_mismatches = "(SELECT count() FROM " +
            TB_FRIEND +
            " LEFT JOIN " + TB_CHILD +
            " ON " + TB_FRIEND + "." + CL_FRIENDTOCHILDLINK + " = " +
            TB_CHILD + "." + CL_CHILD_ID +
            " WHERE " + TB_CHILD + "." + CL_CHILDNAME + " IS NULL)" +
            " AS " + friend_result_cl;
    String full_query = "SELECT " + sq_child_mismatches + "," + sq_friend_mismatches;
    SQLiteDatabase db = this.getWritableDatabase();
    Cursor csr;
    Log.d("RAWQUERYSQL",full_query);
    csr = db.rawQuery(full_query,null);
    return_value.addAll(dumpCursorToStringArrayList(csr,"RAWQUERY"));

    // Fails invalid table
    csr = db.query(null,new String[]{sq_child_mismatches,sq_friend_mismatches},null,null,null,null,null);
    return_value.addAll(dumpCursorToStringArrayList(csr,"SECONDTRY"));
    csr.close();
    return return_value;
}

, а метод dumpCursortoStringArrayList: -

private ArrayList<String> dumpCursorToStringArrayList(Cursor csr, String tablename) {
    ArrayList<String> rv = new ArrayList<>();
    int original_position = csr.getPosition();
    csr.moveToPosition(-1);
    rv.add("Table: " + tablename);
    while (csr.moveToNext()) {
        rv.add("\tRow # " + String.valueOf(csr.getPosition() + 1));
        for (String column: csr.getColumnNames()) {
            rv.add("\t\tColumn: " + column + "\tvalue is: \t" + csr.getString(csr.getColumnIndex(column)));
        }
    }
    csr.moveToPosition(original_position);
    return rv;
}

Я получаю ту же ошибку, еслиЯ пытаюсь "" вместо нуля, например

Если я использую только rawQuery, я получаю

04-22 07:07:33.914 6271-6271/s.q001 I/RESULTS: Table: RAWQUERY
04-22 07:07:33.914 6271-6271/s.q001 I/RESULTS:  Row # 1
04-22 07:07:33.914 6271-6271/s.q001 I/RESULTS:      Column: child_mismatches    value is:   1
04-22 07:07:33.914 6271-6271/s.q001 I/RESULTS:      Column: friend_mismatches   value is:   1

Это от использования

    ArrayList<String> results = DBOpenHelper.checkLinkIntegrity();
    for (String s : results) {
        Log.i("RESULTS",s);
    }

Как я могу выполнить запросс методом запроса вместо метода rawQuery, чтобы получить лучшие оценки?

1 Ответ

2 голосов
/ 22 апреля 2019

Ваша проблема в том, что метод запроса ожидает таблицу, поскольку затем генерирует SQL согласно

SELECT your_columns FROM the_table; 

Поскольку таблицы нет, выдается исключение Invalid Table.

Вы должны предоставить что-то, что будет удовлетворять условию ОТ , оно не может быть ничем.

Вы можете обойти это несколькими способами, и я думаю, что именно домашняя работа пытается заставить вас выяснить / исследовать.

Fix 1

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

csr = db.query(null,new String[]{sq_child_mismatches,sq_friend_mismatches},null,null,null,null,null,"1");
  • Обратите внимание на 8-й параметр, это LIMIT s количество строк, сгенерированных для одной, поскольку для каждой строки в таблице fake будет сгенерирована строка.

Fix 2

или FROM может быть подзапросом (см. Диаграмму), вы можете использовать подзапрос, например. тот, который у вас есть enter image description here

Так что вы можете использовать: -

    csr = db.query(
            sq_child_mismatches, //<<<<<<<<<< the fake subquery
            new String[]{
                    sq_child_mismatches,
                    sq_friend_mismatches
            },
            null    ,null,null,null,null
    );
  • В этом случае, поскольку поддельный подзапрос возвращает одну строку / результат, нет необходимости в предложении LIMIT .
...