SelectionArgs в SQLiteQueryBuilder не работает с целыми значениями в столбцах

Я пытаюсь выбрать некоторые данные из базы данных, и у меня есть два фрагмента кода для этого:

cursor = builder.query(db, new String[]{"col1", "col2", "col3"}, "id = ?", new String[]{getSID(db)}, null, null, null); 

а также

 cursor = builder.query(db, new String[]{"col1", "col2", "col3"}, "id = " + getSID(db), null, null, null, null); 

Разница между ними заключается в том, что первая кажется более правильной в соответствии с документацией, но она также не работает – курсор пуст. Вместо второго – я получаю все данные, которые мне нужны.

Поэтому я попытался выполнить различные SQL-запросы на моем компьютере с копией базы данных, и это то, что у меня есть:

 SELECT col1, col2, col3 FROM SomeTables WHERE (id = '42') 

Этот не работает (и этот запрос, очевидно, равен запросу, сгенерированному первым образцом кода)

 SELECT col1, col2, col3 FROM SomeTables WHERE (id = 42) 

И этот работает отлично (равный запросу из второго образца кода).

Как я знаю, SQLite должен выполнять автоматический запуск типа, но что-то пошло не так, и я не знаю почему. У вас есть идеи о том, как можно исправить первый пример кода? (Или, может быть, база данных?)

Если это имеет значение, вот упрощенный сценарий CREATE таблицы с полем id :

 CREATE TABLE SomeTable ( ID PRIMARY KEY, col1, col2, [...] ) 

UPD: И, кстати, getSID (db) возвращает String Object.

Solutions Collecting From Web of "SelectionArgs в SQLiteQueryBuilder не работает с целыми значениями в столбцах"

Такими параметрами запроса могут быть только строки, это ужасная ошибка дизайна в API баз данных Android.

Несмотря на то, что говорит документация, вы должны использовать параметры только для фактических значений строк; Целочисленные значения могут быть безопасно встроены непосредственно в строку SQL. (Для blobs вы должны использовать функцию, которая принимает ContentValues .)

Обратите внимание: хотя SQLite использует динамическую типизацию , значения разных типов в большинстве случаев не сравниваются одинаково ( SELECT 42='42'; возвращает 0 ). Существуют случаи, когда SQLite автоматически преобразует значения из-за близости типа (в вашем случае это произойдет, если вы id столбец id как INTEGER ), но это довольно противоречиво, поэтому на него не следует полагаться.

Согласно документации SQLite,

Любой столбец базы данных SQLite версии 3, за исключением столбца INTEGER PRIMARY KEY, может использоваться для хранения значения любого класса хранения.

В контексте моего случая это означает, что мы не можем быть уверены, какой тип данных будет храниться в столбцах. Если вы можете управлять и преобразовывать типы данных, когда они помещаются в базу данных, вы можете конвертировать значения id в TEXT при добавлении данных в базу данных и легко использовать selectionArgs . Но это не ответ на мой вопрос, потому что мне приходится иметь дело с содержимым базы данных, как есть.

Итак, возможные решения:

A) вставлять целочисленные значения в строку selection не сворачивая их в:

 cursor = builder.query(db, new String[]{"col1", "col2", "col3"}, "id = " + getSID(db), null, null, null, null); 

Б) отличает значения от выбораArgs: CAST(? as INTEGER) или CAST(id AS TEXT) . Я думаю, что преобразование столбца в TEXT является лучшим решением, потому что правый операнд всегда является TEXT , но левым может быть что угодно. Так:

 cursor = builder.query(db, new String[]{"col1", "col2", "col3"}, "CAST(id AS TEXT) = ?", new String[]{getSID(db)}, null, null, null); 

Вам нужно преобразовать свой int id в string перед передачей в ваш запрос, потому что массив параметров имеет строку типа. Например:

 cursor = builder.query(db, new String[]{"col1", "col2", "col3"}, "id = ?", new String[]{String.valueOf(getSID(db))}, null, null, null); 

Причина, по которой он работает во втором типе запроса, заключается в том, что вы добавляете целочисленное значение со строкой, которая автоматически преобразует int в String. Например:

 int i = 10; String s = i + ""; //now 10 is in string