Привязка параметра запроса в условии LENGTH () не работает - PullRequest
0 голосов
/ 29 марта 2020

У меня возникли проблемы с поиском информации об этой проблеме, но, похоже, это ограничение SQLite.

Рассмотрим простую таблицу words с 2 полями, _id (int) и word (текст). Следующий запрос работает и возвращает ожидаемые результаты (все слова, длина которых не превышает 12 символов):

SELECT * FROM words WHERE LENGTH(word) <= 12;

Однако, если этот предел должен быть динамическим c и преобразован в параметр, запрос no дольше работает. Он возвращает все строки таблицы:

String query = "SELECT * FROM words WHERE LENGTH(word) <= ?";
Cursor cursor = database.rawQuery(query, new String[]{ Integer.toString(12) });

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

String query = "SELECT w.*, LENGTH(w.word) AS word_length FROM words w WHERE word_length <= ?";
Cursor cursor = database.rawQuery(query, new String[]{ Integer.toString(12) });

Является ли моя единственная возможность просто фильтровать результаты запроса после этого? Почему параметризованные условия в обычных столбцах INT работают, а не в LENGTH ()? (например, WHERE _id < ? отлично работает)

Ответы [ 3 ]

1 голос
/ 29 марта 2020

Оператор sql, который выполняется с:

rawQuery(query, new String[]{ Integer.toString(12) });

:

SELECT * FROM words WHERE LENGTH(word) <= '12';

, а не:

SELECT * FROM words WHERE LENGTH(word) <= 12;

, поскольку rawQuery() обрабатывает все передаваемые параметры в виде строк и заключают их в одинарные кавычки. Таким образом, целое число LENGTH(word) сравнивается со строковым литералом, таким как 12, и именно здесь существует особенность SQLite, которая утверждает, что:

Значение INTEGER или REAL меньше, чем любой TEXT или BLOB значение.

(из Типы данных в SQLite версии 3 ). Поэтому все целые числа считаются меньше строкового литерала '12'. Конечно, это не то, что вы хотите и ожидаете, поэтому вы можете принудительно преобразовать '12' в целое число 12, и вы можете сделать это, добавив к нему 0:

String query = "SELECT * FROM words WHERE LENGTH(word) <= ? + 0";

Это неявное преобразование '12' в 12, потому что вы применяете к нему операцию Numberri c.

0 голосов
/ 29 марта 2020

Вы пробовали Integer.parseInt()? Я думаю, что ваш запрос нуждается в целочисленном параметре, и вы конвертируете его в строку:)

0 голосов
/ 29 марта 2020

Конечно, как только я это сделаю, я смогу найти обходной путь, приведя поле к целому числу:

String query = "SELECT * FROM words WHERE CAST(LENGTH(word) AS INTEGER) <= ?";
Cursor cursor = database.rawQuery(query, new String[]{ Integer.toString(12) });

Кажется чрезмерным, но я думаю, что возвращаемое значение LENGTH () не считается целым числом (вся документация, с которой я столкнулся, просто говорит, что она «возвращает количество символов»)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...