Android的SQLite的选择ARGS []不正确的值? [英] Android Sqlite selection args[] incorrect value?

查看:249
本文介绍了Android的SQLite的选择ARGS []不正确的值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个查询的不同变体。所有的值类型是字符串! (不要问为什么......)
第一种可能是这样的:

  SELECT * FROM项,其中Arg1 = FALSE

为ARG(S)的字符串(sqlWhere)如下:
ARG1 =?

在索引0的ARG(S)-array(参数)的字符串看起来是这样的:

这工作正常。我有715的效果。

现在,如果我有这样的事情:

  SELECT * FROM项WHERE(ARG1 = 40或ARG2 = 42)和参数3 = FALSE

我会想到110结果这一点。但目前还没有任何结果,不会抛出异常。

如果我会产生在Firefox的SQLite Manager中的原始查询:

  SELECT COUNT(*)FROM项WHERE(ARG1 = 40或ARG2 = 42)和参数3 = FALSE

我会得到错误:没有这样的列:假
如果我生成一个查询是这样的:

  SELECT COUNT(*)FROM项WHERE(ARG1 = 40或ARG2 = 42),ARG3 =假

这会不会失败。但。我使用selectionArgs两个。我读过,他们应该避免这种情况。但他们没有。甚至,如果我投入selectionArgs两个为ARG3 =\\+假+\\或参数3 =\\'+假+\\',甚至ARG3 ='+假+ '这是行不通的。也许一个Android的具体问题?
值假来源于值的列表。它被初始化用emty串。

查询的方法是这样的:

 公开名单<地图<字符串,字符串>> getSearchResults(字符串sqlWhere,字串[] args)
    {
        清单<地图<字符串,字符串>>规格=新的ArrayList<地图<字符串,字符串>>();
        的String [] = specnames this.getSpecNames();        光标光标= mDb.query(dbSchema.SpecSchema.TABLE_NAME,specnames,sqlWhere,ARGS,NULL,NULL,dbSchema.SpecSchema._ID + dbSchema.SORT_ASC);
        cursor.moveToFirst();
        而(!cursor.isAfterLast())
        {
            地图<字符串,字符串>临时=新的HashMap<字符串,字符串>();
            的for(int i = 0; I< specnames.length;我++)
                temp.put(specnames [I],cursor.getString(cursor.getColumnIndex(specnames [I])));
            specs.add(临时);            cursor.moveToNext();
        }        如果(指针!= NULL)
            cursor.close();        返回规范;
    }


解决方案

有关文档<一个href=\"http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#query%28java.lang.String,%20java.lang.String%5B%5D,%20java.lang.String,%20java.lang.String%5B%5D,%20java.lang.String,%20java.lang.String,%20java.lang.String,%20java.lang.String%29\"相对=nofollow> SQLiteDatabase.query() 说:


  

selectionArgs两个的 - 你可能包括S IN的选择,这将是从selectionArgs两个值进行更换,以使他们出现在哪里?
  在选择。 的值将被绑定为字符串。


当你执行这个查询:

  SELECT * FROM项WHERE(ARG1 = 40或ARG2 = 42)和参数3 = FALSE

和绑定使用 selectionArgs两个 -parameter,整数和布尔将被绑定为字符串参数。这是不一样的数据库中。我知道你说你所有的列键入文本,但看过的 SQLite的文档


  

列的类型亲和力的数据推荐类型存储
  在该列。
这里最重要的想法是,的类型
  推荐的,不是必需的。任何列仍可以存储任何类型的
  数据。
这只是一些列,有选择,将preFER到
  使用一个存储类另一些人。


这意味着,当你在你的字符串表中插入你的整数值,SQLite的将这些转换并存储为整数。下一个重要的一点是比较


  

SQLite的可能尝试的存储类之间进行转换值
  INTEGER,REAL,和/或执行一个比较之前的文本。
  [...]


  
  

      
  • 一名前pression这是一个简单的参考一列值有作为列相同的亲和力

  •   

该文档给出了下面的例子:

  CREATE TABLE T1(
    一文, - 文字亲和力
    b NUMERIC, - 数字亲和力
    ÇBLOB, - 无亲和力
    ð - 没有亲和力
); - 因为A列有文字的亲和力,在数值
- 比较的右手侧被转换前为文本
- 发生的比较。
选择A&LT; 40,读取&lt; 60,读取&lt; 600从T1;
0 | 1 | 1

在你的情况,这意味着以下内容:


  1. TEXT -table被插入整数,然后将其转换(储存)为 INTEGER 秒。

  2. 当执行你的比较,你给 TEXT - 值(这是你的整数)。这些应该是(但不必是)转换为 TEXT - 值,因为你的表显示它的值类型的文本

  3. 您比较 INTEGER 文本,这不等于并为此不给你正确的结果。


要插入不同的数据类型(其它则字符串)进入SQLiteDatabase,使用<一个href=\"http://stackoverflow.com/questions/433392/how-do-i-use-$p$ppared-statements-in-sqlite-in-android\">$p$ppared声明的。

I have different variants of a query. All value types are Strings! (don't ask why...) The first one might look like this:

SELECT * FROM item WHERE arg1=false

The string ("sqlWhere") for the arg(s) looks like this: "arg1=?"

The string for the arg(s)-Array (args) at index 0 looks like this: "false"

This works fine. I've got 715 results.

Now, if i have something like this:

SELECT * FROM item WHERE (arg1=40 OR arg2=42) AND arg3=false

I'll expect 110 results for this. But there aren't any results, no Exception is thrown

If I'll generate a raw query in Firefox SQLite Manager:

SELECT COUNT(*) FROM item WHERE (arg1=40 OR arg2=42) AND arg3=false

I'll get the error: "no such column: false" If I generate a query like this:

SELECT COUNT(*) FROM item WHERE (arg1=40 OR arg2=42) AND arg3="false"

It'll not fail. BUT. I'm using selectionargs. I've read, that they should AVOID this situation. But they don't. Even, If I put into the selectionargs for arg3 = "\"+"false"+"\"" or arg3 = "\'+"false"+"\'" or even arg3="'"+"false"+"'" it won't work. Maybe an android specific problem? The value "false" comes from a list of values. It is initialized with an emty string.

Query-Method looks like this:

public List<Map<String,String>> getSearchResults(String sqlWhere, String[]args)
    {
        List<Map<String,String>> specs = new ArrayList<Map<String,String>>();
        String[] specnames = this.getSpecNames();

        Cursor cursor = mDb.query(dbSchema.SpecSchema.TABLE_NAME, specnames, sqlWhere, args, null, null, dbSchema.SpecSchema._ID + dbSchema.SORT_ASC);
        cursor.moveToFirst();
        while(!cursor.isAfterLast())
        {
            Map<String, String> temp = new HashMap<String, String>();
            for(int i = 0; i < specnames.length; i++)
                temp.put(specnames[i], cursor.getString(cursor.getColumnIndex(specnames[i])));
            specs.add(temp);

            cursor.moveToNext();
        }

        if(cursor != null)
            cursor.close();

        return specs;
    }

解决方案

The documentation for SQLiteDatabase.query() says:

selectionArgs - You may include ?s in selection, which will be replaced by the values from selectionArgs, in order that they appear in the selection. The values will be bound as Strings.

When you execute this query:

SELECT * FROM item WHERE (arg1=40 OR arg2=42) AND arg3=false

and bind the arguments using the selectionArgs-parameter, the integers and the boolean will be bound as strings. This is not the same as in your database. I know you said all your columns are of type TEXT, but read the SQLite Documentation:

The type affinity of a column is the recommended type for data stored in that column. The important idea here is that the type is recommended, not required. Any column can still store any type of data. It is just that some columns, given the choice, will prefer to use one storage class over another.

That means, when you insert your integer values in your string-table, SQLite will convert those and store them as integers. The next important point is comparison:

SQLite may attempt to convert values between the storage classes INTEGER, REAL, and/or TEXT before performing a comparison. [...]

  • An expression that is a simple reference to a column value has the same affinity as the column.

The docs give the following example:

CREATE TABLE t1(
    a TEXT,      -- text affinity
    b NUMERIC,   -- numeric affinity
    c BLOB,      -- no affinity
    d            -- no affinity
);

-- Because column "a" has text affinity, numeric values on the
-- right-hand side of the comparisons are converted to text before
-- the comparison occurs.
SELECT a < 40,   a < 60,   a < 600 FROM t1;
0|1|1

In your case that means the following:

  1. Your TEXT-table gets integers inserted, which are then converted (and stored) as INTEGERs.
  2. When performing your comparison, you give in TEXT-values (which are your integers). Those should be (but don't need to be) converted to TEXT-values, because your table indicates it's values are of type TEXT.
  3. You compare INTEGER to TEXT, which is not equal and therefor doesn't give you the correct results.


To insert different data-types (other then string) into the SQLiteDatabase, use Prepared Statements.

这篇关于Android的SQLite的选择ARGS []不正确的值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆