Sqlite:SqliteDatabase.delete()vs原始查询

时间:2017-10-20 20:12:47

标签: android sqlite

结论: Android的数据库API 工作但文档非常不完整。

由于Sqlite提供的灵活性,我最近遇到了大脑破坏的情况,因为在创建表时不强制您指定数据类型。我的心态是假设每个数据类型都是一般字符序列(如果没有指定),因此与数据库通信的方式是java.lang.String

但是当你看到如下方法时,你不能怪我:

int delete (String table, 
                String whereClause, 
                String[] whereArgs)
来自Android docsSqlDatabase课程中的

我的表格包含电话号码(我存储为java.lang.String)和时间戳作为长字段。当我尝试使用这种方法删除记录时,尽管进行了无数的调试,它仍然没有被删除。

我检查了所有内容并且查询没有问题,表格存在且所有清单都是偶然的,我发现在以原始方式查询而不是使用上述方法时删除时间戳周围的''会产生成功删除,像这样:

DELETE FROM messages_records_table WHERE messageTimestamp = 1508494606000;

而不是以下内容:

DELETE FROM messages_records_table WHERE messageTimestamp = '1508494606000';

,或者

DELETE FROM messages_records_table WHERE messageTimestamp = "1508494606000";

电话号码不是问题;这是在INSERTION / DELETION

中创建问题的时间戳

因此,我尝试运行原始删除查询,删除了引号(字符串/ varchar类型需要),并且它成功删除。我使用了以下方法:

db.execSQL(String sql, Object[] whereArgs)

此处需要注意的关键是,与Object[]相比,String[]delete()不同。我传递了一个Long to Object来使其工作,但在Long.toString()中传递delete()似乎毫无用处。

所以我的问题是,我的分析是否正确,delete() API基本没用,或者我错过了一些更大的图片......毕竟,它是由Android团队提供的吗?

2 个答案:

答案 0 :(得分:1)

SQLite支持multiple data types;虽然没有严格执行列类型,但在某些情况下可能会自动转换值(这称为affinity)。

当您的值存储为数字时,您应该以数字形式访问它们,而不是字符串。

Android数据库API不允许您在大多数函数中使用字符串以外的参数类型。这是一个可怕的设计错误。

要搜索数字,请使用execSQL()(允许您使用数字参数)或将字符串值转换回数字:

db.delete(..., "timestamp = CAST(? AS NUMBER)",
          new String[]{ String.valueOf(ts) });

答案 1 :(得分:0)

  

问题是我的心态假设每种数据类型都是   一般字符序列,如果没有指定,因此的方式   与数据库交谈是通过java.lang.String。

我认为这是真正的问题。

如果您没有指定类型,例如

CREATE TABLE mytable (col1,col2,col3)

然后根据Determination of Column Affinity(3.1)规则3: -

  

3)如果列的声明类型包含字符串" BLOB"或者如果没有   指定了类型,然后该列具有关联BLOB。

然后根据第3节

  

具有亲和力BLOB的列不喜欢一个存储类   另一个并没有尝试强制来自一个存储类的数据   到另一个。

我个人从未遇到过删除问题。但是我确实总是根据rowid删除。

以下是一个实际工作示例用法,显示 delete 没有用,并且正在删除很长时间。但是列的类型都是INTEGER: -

        int pudeletes;
        int sldeletes;
        int rdeletes;
        int pdeletes;

        if(doesProductExist(productid)) {

            // if not in a transaction then begin a transaction
            if(!intransaction) {
                db.beginTransaction();
            }

            String whereargs[] = { Long.toString(productid)};

            // Delete ProductUsage rows that use this product
            pudeletes = db.delete(
                    DBProductusageTableConstants.PRODUCTUSAGE_TABLE,
                    DBProductusageTableConstants.PRODUCTUSAGE_PRODUCTREF_COL +
                            " = ?",
                    whereargs
            );

            // Delete ShopList rows that use this product
            sldeletes = db.delete(
                    DBShopListTableConstants.SHOPLIST_TABLE,
                    DBShopListTableConstants.SHOPLIST_PRODUCTREF_COL +
                            " = ?",
                    whereargs
            );

            // Delete Rules rows that use this product
            rdeletes = db.delete(
                    DBRulesTableConstants.RULES_TABLE,
                    DBRulesTableConstants.RULES_PRODUCTREF_COL +
                            " = ?",
                    whereargs
            );

            // Delete the Product
            pdeletes = db.delete(
                    DBProductsTableConstants.PRODUCTS_TABLE,
                    DBProductsTableConstants.PRODUCTS_ID_COL +
                            " = ?",
                    whereargs
            );

            // if originally not in a transaction then as one was started
            // complete and end the transaction
            if(!intransaction) {
                db.setTransactionSuccessful();
                db.endTransaction();
            }
        }