使用查询字符串在Android SQLiteDatabase中执行插入/更新/删除的正确方法是什么?

我一直在查看官方文档( http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html)以及与StackOverflow帖子和实际观察到的行为的交叉引用,并且文档似乎具有误导性,并且可能在几个方面都是错误的.

我正在尝试执行参数化查询以插入/更新/删除,就像使用rawQuery(String sql,String []参数)进行选择一样.我需要通过查询而不是在SQLiteDatabase类上使用insert / update / delete方法来执行此操作,因为在许多情况下,查询跨越多个表,并且在任何情况下我们都编写了一组我们用于此app的查询在我们所有的平台上(也为SQLite编写),最好是按原样使用它.

这是我发现令人困惑/误导的内容:

> doc告诉rawQuery语句不能用分号终止,但它实际上似乎没有任何区别.这对我很重要,因为我们有一个巨大的XML文档,里面填充了我在我的应用程序中跨多个平台使用的查询,如果可能的话,我更愿意保持相同.
> rawQuery似乎不适用于插入(是的,我尝试使用和不使用分号).该文件没有说明这一点.我确实看到它返回一个Cursor,我想这可能是一个倾斜提示,它只适用于select,但不一定 – 它可以简单地返回零长度或null Cursor,当它们没有结果集时.
> execSQL(String sql,Object [] bindArgs)明确表示它不适用于插入,但事实上确实如此!
>此外,尽管execSQL(String,Object [])明确告诉您不要尝试CRUD操作,但它的无参数版本不包含此类警告,并且也可以正常工作(缺点是不允许SQL参数).

所有这一切的结果是,我能够找到成功执行带参数化参数的插入的唯一方法是使用文档明确指示您不要用于此目的的一种工作方法.

另外,对于插入/更新/删除来说,rawQuery无法正常工作,因为我们有一个通用的数据层,如果我们可以使用单个统一的API调用来运行我们所有的CRUD查询,那将更加优雅.数据库.

那么这里发生了什么?这份文件是否已经过时了?是否可以使用execSql来执行插入,更新等操作?有没有人成功使用rawQuery进行插入?

附录:

针对OS运行:Android 4.3.

示例查询(什么工作,什么不工作)

// Works
db.execSql("INSERT into MyTable (Col1,Col2) VALUES (?,?)",new String[] { "Foo","Bar" });
db.execSql("INSERT into MyTable (Col1,?);","Bar" });

// No exception thrown,but no changes made to the database
db.rawQuery("INSERT into MyTable (Col1,"Bar" });
db.rawQuery("INSERT into MyTable (Col1,"Bar" });

解决方法

你是对的.文档令人困惑.总的来说,该设计试图围绕sqlite3 C API提供方便的Java包装器.在大多数情况下,如果按照设计师的意图使用它,它可以正常工作,例如:使用便捷方法进行CRUD操作.但是,对于方便的CRUD方法不够强大或根本不适用(CREATE TABLE等)的情况,他们还需要提供原始查询方法execSQL()和rawQuery().这会导致泄漏抽象.

The doc says for rawQuery that statements must not be terminated by a semicolon,but it doesn’t actually seem to make any difference. This matters to me because we have a huge XML document filled with queries I use in my app across several platforms and I’d prefer to keep it identical if possible.

文档很糟糕.实际上,Android SQLiteDatabase本身就是calls rawQuery with a semicolon-terminated query string.

rawQuery doesn’t seem to work for inserts (yes,I’ve tried with and without the semicolon). The doc don’t say anything about this. I do see that it returns a Cursor,which I suppose could be an oblique hint that it only works with a select,but not necessarily — it could simply return a zero-length or null Cursor when they was no result set.

它确实有效,但您需要了解它在本机级别上的工作原理.

将execSQL()视为运行查询的sqlite3_exec()并返回成功或错误代码.

将rawQuery()视为编译查询但尚未运行的sqlite3_prepare().要实际运行它,请使用Cursor上的moveTo …()方法之一.可以将其视为sqlite3_step().将任何rawQuery()与moveTo …()组合将实际改变数据库.

execSQL(String sql,Object[] bindArgs) explicitly says that it does not work with selects,but in fact it does!

Furthermore,although execSQL(String,Object[]) specifically tells you not to try CRUD operations,its parameterless version contains no such warning,and also works fine for that purpose (with the disadvantage of not allowing SQL parameters).

它适用于所有CRUD操作.对于CRUD的R读取部分,无法获得所选数据.

相关文章

Android性能优化——之控件的优化 前面讲了图像的优化,接下...
前言 上一篇已经讲了如何实现textView中粗字体效果,里面主要...
最近项目重构,涉及到了数据库和文件下载,发现GreenDao这个...
WebView加载页面的两种方式 一、加载网络页面 加载网络页面,...
给APP全局设置字体主要分为两个方面来介绍 一、给原生界面设...
前言 最近UI大牛出了一版新的效果图,按照IOS的效果做的,页...