24.Linux:嵌入式sqlite3数据库事务理解以及实例操作 (转载)

2019-07-12 19:50发布

[Sqlite]嵌入式数据库事务理解以及实例操作  来自:http://www.runoob.com/sqlite/sqlite-transaction.html 第一部分;shell指令操作 SQLite 事务(Transaction 事务(Transaction)是一个对数据库执行工作单元。事务(Transaction)是以逻辑顺序完成的工作单位或序列,可以是由用户手动操作完成,也可以是由某种数据库程序自动完成。 事务(Transaction)是指一个或多个更改数据库的扩展。例如,如果您正在创建一个记录或者更新一个记录或者从表中删除一个记录,那么您正在该表上执行事务。重要的是要控制事务以确保数据的完整性和处理数据库错误。 实际上,您可以把许多的 SQLite查询联合成一组,把所有这些放在一起作为事务的一部分进行执行。 事务的属性 事务(Transaction)具有以下四个标准属性,通常根据首字母缩写为 ACID ·        原子性(Atomicity):确保工作单位内的所有操作都成功完成,否则,事务会在出现故障时终止,之前的操作也会回滚到以前的状态。 ·        一致性(Consistency)确保数据库在成功提交的事务上正确地改变状态。 ·        隔离性(Isolation):使事务操作相互独立和透明。 ·        持久性(Durability):确保已提交事务的结果或效果在系统发生故障的情况下仍然存在。 事务控制 使用下面的命令来控制事务: ·        BEGIN TRANSACTION:开始事务处理。 ·        COMMIT:保存更改,或者可以使用 ENDTRANSACTION 命令。 ·        ROLLBACK:回滚所做的更改。 事务控制命令只与 DML命令 INSERTUPDATE DELETE 一起使用。他们不能在创建表或删除表时使用,因为这些操作在数据库中是自动提交的。 BEGIN TRANSACTION 命令 事务(Transaction)可以使用 BEGIN TRANSACTION命令或简单的 BEGIN命令来启动。此类事务通常会持续执行下去,直到遇到下一个 COMMIT ROLLBACK 命令。不过在数据库关闭或发生错误时,事务处理也会回滚。以下是启动一个事务的简单语法: BEGIN;   or   BEGIN TRANSACTION; COMMIT 命令 COMMIT 命令是用于把事务调用的更改保存到数据库中的事务命令。 COMMIT 命令把自上次 COMMIT ROLLBACK 命令以来的所有事务保存到数据库。 COMMIT 命令的语法如下: COMMIT;   or   END TRANSACTION; ROLLBACK 命令 ROLLBACK 命令是用于撤消尚未保存到数据库的事务的事务命令。 ROLLBACK 命令只能用于撤销自上次发出 COMMIT ROLLBACK 命令以来的事务。 ROLLBACK 命令的语法如下: ROLLBACK; 实例 假设 COMPANY表有以下记录: ID         NAME        AGE         ADDRESS     SALARY ----------  ----------  ----------  ----------  ---------- 1           Paul        32          California  20000.0 2           Allen       25          Texas       15000.0 3           Teddy      23          Norway     20000.0 4           Mark        25          Rich-Mond  65000.0 5           David       27          Texas       85000.0 6           Kim         22          South-Hall 45000.0 7           James       24          Houston     10000.0 现在,让我们开始一个事务,并从表中删除 age = 25的记录,最后,我们使用 ROLLBACK命令撤消所有的更改。 sqlite> BEGIN; sqlite> DELETE FROM COMPANY WHERE AGE= 25; sqlite> ROLLBACK; 检查 COMPANY表,仍然有以下记录: ID         NAME        AGE         ADDRESS     SALARY ----------  ----------  ----------  ----------  ---------- 1           Paul        32          California  20000.0 2           Allen       25          Texas       15000.0 3           Teddy       23          Norway      20000.0 4           Mark        25          Rich-Mond  65000.0 5           David       27          Texas       85000.0 6           Kim         22          South-Hall 45000.0 7           James       24          Houston     10000.0 现在,让我们开始另一个事务,从表中删除 age = 25的记录,最后我们使用 COMMIT命令提交所有的更改。 sqlite> BEGIN; sqlite> DELETE FROM COMPANY WHERE AGE= 25; sqlite> COMMIT; 检查 COMPANY表,有以下记录: ID         NAME        AGE         ADDRESS     SALARY ----------  ----------  ----------  ----------  ---------- 1           Paul        32          California  20000.0 3           Teddy      23          Norway     20000.0 5           David       27          Texas       85000.0 6           Kim         22          South-Hall 45000.0 7           James       24          Houston     10000.0
第二部分:sqlite3数据库函数操作(即API): 来自:http://blog.csdn.net/mwkfeng/article/details/5903125/ 原因:它以文件的形式存在磁盘中,每次访问时都要打开一次文件,如果对数据库进行大量的操作,就很慢。 解决办法:用事物的形式提交,因为开始事务后,进行的大量操作语句都保存在内存中,当提交时才全部写入数据库,此时,数据库文件也只用打开一次。如果操作错误,还可以回滚事务。 接口:事务的操作没有特别的接口函数,就是一个普通的 sql 语句而已,分别如下:   int ret ; 
ret = sqlite3_exec ( db , "begin transaction" , 0 , 0 , & zErrorMsg ); // 开始一个事务 

ret = sqlite3_exec ( db , "commit transaction" , 0 , 0 , & zErrorMsg ); // 提交事务 

ret = sqlite3_exec ( db , "rollback transaction" , 0 , 0 , & zErrorMsg );
例程:在进行大量的操作前使用如下语句 

ret = sqlite3_exec ( db , "begin transaction" , 0 , 0 ,& zErrorMsg ); 
for (...) 
{ 
  //insert into operate 

  
  // 如果操作错误 

 ret = sqlite3_exec ( db , "rollback transaction" , 0 , 0 , & zErrorMsg ) 
} 
ret = sqlite3_exec ( db , "commit transaction" , 0 , 0 , & zErrorMsg );   开发过程遇到这样的问题: 分别对两个数据库文件的不同表进行操作,执行顺序为: open db A->begin trasaction->open db B->select from db B->close db B->select from db A->rollbak or commit->close db A 测试发现, select from db B 这一步会出错,错误信息为library routine called out of sequence ,出错后执行rollback ,这一步也会报错。 原来以为原因是:开始一个事务只能对一个数据库进行操作。 测试发现,即使不开始事务,执行顺序为: open db A->open db B->select from db B->close db B->select from db A->close db A , 仍会出现ibrary routine called out of sequence 的错误。 难道打开一个数据库,在关闭其之前不能打开其他数据库? 难道sqlite 的并发执行需要用户自己来控制?   今天发现,以上出错原因可能是总控程序和子程序的全局变量一致(都是sqlite3 *db ),导致总控程序的全局变量被修改。 具体还需进一步研究。