我目前正在实现一些依赖于SQLite数据库的功能。在这样做的同时,我遇到了一个我没想到的限制。这让我想知道我是否正确地解决了我的问题。我希望有人能提出一种考虑到要求的不同方法。
目标
目标是尽可能快地将大量对象存储到数据库中。但是,如果在任何时候确定不应该存储这些对象,则操作不应对数据库产生任何影响。确切的存储查询('插入')取决于先前的插入。
使用案例
考虑一个非常大的'实例信息包'集合,每个包代表一些相应抽象实例的知识的一部分。因此,总集合代表了一个或多个抽象实例的完整知识。每个包的信息包括:
在表中找到instance_id和attribute_id,分别为TBL_INSTANCES和TBL_ATTRIBUTES。这里使用的数据库模型是EAV模型。
插入后,表格TBL_ENTRIES应包含以下格式的条目:
[ entry_id | instance_id | attribute_id | attribute_value ]
问题
实施似乎很简单:
不幸的是,在查找步骤(4.1和4.2.1)中,SQLite报告“无法在事务中启动事务”错误。阅读文档,似乎是查找调用sqlite3_exec例程的事实,除非我错了,似乎在内部设置了一个事务。
问题
如果不允许嵌套事务,我应该如何执行查找步骤(基本上是“INSERT OR REPLACE”表达式后跟“SELECT”查询)?有没有办法避免它们或在当前事务中使用sqlite3_exec?如果没有,我是否以错误的方式处理我的问题?也许我不应该使用单独的整数作为键,例如直接使用attribute_uri作为键,而不是查找相应的attribute_id。
在任何情况下,我仍然需要在事务期间做一些相同的事情,因为真正的速度增益在于准备实例集合上的语句,而不是属性集合:实例可能只有一个或两个属性,而实例集合中的实例数总是非常大。
我正在使用C / C ++,SQLite 3.7。
对我的方法有任何建议或评论,我们非常感谢!
答案 0 :(得分:5)
来自SQLite documentation on BEGIN TRANSACTION:
使用BEGIN ... COMMIT创建的事务不会嵌套。对于嵌套 事务,使用SAVEPOINT和RELEASE命令
我似乎记得嵌套事务应该已经存在于任何SQLite 3.7。*。