SQLiteStatement 执行一个 SELECT / INSERT / DELETE / UPDATE
Posted
技术标签:
【中文标题】SQLiteStatement 执行一个 SELECT / INSERT / DELETE / UPDATE【英文标题】:SQLiteStatement execute a SELECT / INSERT / DELETE / UPDATE 【发布时间】:2012-11-02 03:59:14 【问题描述】:我在优化 SQLite 事务时使用了带有事务的编译 SQLiteStatement
,但我正在阅读 execute
函数的文档:
执行这条SQL语句,如果不是SELECT/INSERT/DELETE/UPDATE,例如CREATE/DROP表、视图、触发器、索引等。
这似乎暗示这个函数不应该与SELECT / INSERT / DELETE / UPDATE
语句一起使用,但我有代码可以将它与插入一起使用并且可以工作。
我知道executeInsert
和其他方法,但是executeUpdateDelete
在我的API 级别中不可用,那么我可以使用execute
吗?
另外,如果我不需要最后一个插入 id 或受影响的行数,我应该使用execute
而不是executeInsert
等,换句话说,它更有效吗?
【问题讨论】:
【参考方案1】:execute
可能不会比executeInsert
快,甚至可能更慢(在 ICS 上 execute
调用 executeUpdateDelete
并丢弃返回值)。您需要对其进行测试,但我怀疑您会在这里找到真正的区别。
AFAIK,如果您不需要返回值,则仅使用 execute
是安全的,但我不会指望在未来的 android 版本中保持这种状态。文档说不,所以也许有人会改变行为以反映这一点。较旧的实现似乎也使用execute
(例如2.1 delete()
sourcecode)。例如,Jelly Bean 在 SQLite 的幕后更改了 a lot,但在使用 execute
时它仍然可以工作
此外,如果您不一遍又一遍地使用相同的 SQLiteStatement
而只是重新绑定 args,那么它可能不值得使用它。与实际的数据库访问和所需的磁盘 I/O 相比,每次调用常规的 insert
、update
、... 方法时都构建一个新的。另一方面,事务有很大帮助,因为在磁盘上为每个语句同步数据库状态真的很慢。
【讨论】:
所以你的意思是不能保证execute()
将在未来发布也与INSERT statement
一起工作而且文档只是混淆它说它Execute this SQL statement, if it is not a SELECT / INSERT /....
然后它不应该执行INSERT
(因为这是我测试过的唯一声明)及其工作!并感谢您提供宝贵的信息:)
还有 statement.executeUpdateDelete();
这在 API 11 中可用 2.2 的任何解决方法?
@MuhammadBabar 该文档试图告诉您execute
方法不适用于有结果的语句。就像为选择设置的行一样,更新/删除的更改计数或插入的最后一行 ID。到目前为止,还没有任何代码可以防止这些意外语句起作用。也许未来对数据库架构的改变会发生,我不知道。 android 框架工程师可以在不通知的情况下轻松添加这样的更改,因为该方法的描述警告您,它多年来将无法工作。
在 2.2 中,获取更新/删除语句的结果更改计数的唯一方法是使用 SQLiteDatabase#update 或 delete
。这些方法在内部对每个方法调用使用新的SQLiteStatement
。他们使用SQLiteStatement#execute()
,然后通过SQLiteDatabase
的隐藏方法记录更改计数。该隐藏方法最终在 API 11 中公开以供 SQLiteStatement
使用,但之前没有。
delete()
或 executeUpdateDelete()
哪个更快?【参考方案2】:
使用SQLiteDatabase 而不是SQLiteStatement 与您的数据库进行交互。 SQLiteStatements 不是线程安全的,所以我不会将它们用于 SELECT / INSERT / DELETE / UPDATE。此外,您应该尽量不要将原始数据库查询用于Selects
以外的任何内容。有内置的辅助函数可以提高您的数据库性能。在您的 SQLiteDatabase
实例上,您有 .insert、.update、.delete,我使用 .rawQuery 进行选择。
【讨论】:
但不是THREAD-SAFE
仅暗示 多线程 应用程序。对于单线程,如果您想要批量插入,则值得使用。
嗯,每个带有数据库的应用程序都应该是多线程的。对磁盘、数据库或 Web 服务的任何请求都应脱离 UI 线程。如果您阻止 UI 线程进行批量插入,那么您做错了。
@JustinMorris:如果只有一个工作线程访问数据库,调用非线程安全方法就可以了。应用程序是多线程的这一事实不是问题,因为主线程不访问数据库。以上是关于SQLiteStatement 执行一个 SELECT / INSERT / DELETE / UPDATE的主要内容,如果未能解决你的问题,请参考以下文章