Intereting Posts
Android: прокладка оставила растровое изображение с белым цветом Как добавить символы валюты в формате pdf, созданные моим приложением? Сохранение растрового изображения на SD-карту без сжатия его в Android Внедрение шаблона DAO в Android-проекте Реализация TabListener с использованием библиотеки поддержки Обновление модуля Titanium Android до SDK 6.0.0 Почему мое приложение не отображается в Google Play? Только что опубликовано Текстуры Android OpenGL: создание и удаление их на лету Какова цель использования переводимых в Android-строк? Хорошо ли заменить широковещательный приемник с помощью Greenrobot Eventbus для запуска функций на основе событий и передачи данных от службы к активности? Android Studio – «Android-инфраструктура обнаружена в проекте» Что такое SDK Patch Applier в Android SDK Tool? Android Сохранение созданных растровых изображений в каталог на SD-карте Android API Google Maps не работает с debug.keystore Android-приложение в haskell

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.

Такими параметрами запроса могут быть только строки, это ужасная ошибка дизайна в 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