两个sqlite对象,链接同一个数据库,断开其中一个sqlite链接,另一个也跟着断开,怎么解决 10
2017-12-18 · 知道合伙人互联网行家
SQLite是一个开源的、内嵌式的关系型数据库。SQLite和Oracle和Access一样是文件型数据库,就是说,一个数据库就是一个文件,此数据库里可以建立很多的表,可以建立索引、触发器等等,但是它实际上得到的就是一个文件。SQLite数据库具有下面的特点:
(1)首先SQLite数据库服务器就在你的数据库应用程序中,其好处是不需要网络配置和管理,也不需要通过设置数据源访问数据库服务器。
(2)其次SQLite数据库的服务器和客户端运行在同一个进程中。这样可以减少网络访问的消耗,简化数据库管理,使你的程序部署起来更容易。
(3)再次SQLite在处理数据类型时与其它的数据库不同。区别在于它所支持的类型以及这些类型是如何存储、比较、强化(enforc)和指派(assign)。
SQLite的域完整性被称为域亲和性(affinity)。为了理解类型亲和性,你必须先要理解存储类和弱类型(manifesttyping)。SQLite有Integer、Real、Text、Blob和Null五个原始的数据类型,被称为存储类。存储类这个词表明了一个值在磁盘上存储的格式,其实就是类型或数据类型的同义词。
数据库SQLite的数据库架构
SQLite在架构上采用了模块的设计,它由公共接口、编译器系统、虚拟机和后端四个子系统组成。
1、接口(Interface)。由SQLite C API组成,也就是说不管是程序、脚本语言还是库文件,最终都是通过它与SQLite交互的(我们通常用得较多的ODBC/JDBC最后也会转化为相应C API的调用)。
2、编译器(Compiler)。在编译器中,分词器(Tokenizer)和分析器(Parser)对SQL进行语法检查,然后把它转化为底层能更方便处理的分层的数据结构---语法树,然后把语法树传给代码生成器(code generator)进行处理。而代码生成器根据它生成一种针对SQLite的汇编代码,最后由虚拟机执行。
3、虚拟机(Virtual Machine)。架构中最核心的部分是虚拟机,或者叫做虚拟数据库引擎(Virtual Database Engine,VDBE)。它和Java虚拟机相似,解释执行字节代码。VDBE的字节代码由128个操作码(opcodes)构成,它们主要集中在数据库操作。它的每一条指令都用来完成特定的数据库操作(比如打开一个表的游标)或者为这些操作栈空间的准备(比如压入参数)。
4、后端(Back-End)。后端由B-树(B-tree),页缓存(page cache,pager)和操作系统接口(即系统调用)构成。B-tree和page cache共同对数据进行管理。B-tree的主要功能就是索引,它维护着各个页面之间的复杂的关系,便于快速找到所需数据。而pager的主要作用就是通过OS接口在B-tree和Disk之间传递页面。
嵌入式数据库SQLite的数据类型
在SQLite数据库中,不仅提供了储存基本数据的功能,而且提供了对二进制数据存储的能力,这样可以确保把采集到的农业图像信息存放到数据库中,由数据库统一操作和管理,在SQLite数据库中提供的基本数据类型不但可以进行转化,还可以进行大小比较。数据类型如下:
(1)Integer整数值。有正负之分,它是由8个字节(Bytes)表示。SQLite数据库可以根据整数值的大小自动控制其所占字节的个数。
(2)Real实数类型。在SQLite由8个字节来表示。
(3)Text文本字符数据类型。用来保存文本信息。SQLite数据库支持多种字符编码类型,包括UTF-8和UTF-16。字符串的大小是没有限制的。
(4)Blob二进制数据对象类型。保存二进制数据,大小没有限制。
(5)Null空类型。一个具有NULL存储类型的值比所有其它类型值都小。SQLite数据库对Null完全支持。
SQLite 数据库本身一共有80多个API调用接口,功能简单的数据库程序用三个接口完成: sqlite3_open(),sqlite3_exec(), 和 sqlite3_close()。 要是想更好的控制数据库引擎,使用sqlite3_prepare()函数把SQL语句编译成字节码再通过sqlite3_step()函数来执行。在SQLite中,绝大多数接口提供了UTF-8和UTF-16两个版本,大多数接口成对出现。
此外,SQLite数据库中同时也提供了用户对API接口扩充的机制。SQLite的扩充API用来支持用户定义的函数、聚合和排序法。实现一个用户自定义的函数分为两步。首先,写句柄。句柄实现一些你想通过SQL完成的功能。然后,注册句柄。为它提供SQL名称、参数的数量和一个指向句柄的指针。
数据库控制和语句执行方式
从数据库打开开始,SQLite就要为sqlite3 *类型准备好内存,一直到数据库关闭整个过程。打开数据库时,这个类型的变量指向你将操作的数据库。SQLite数据库和大多数据库操作相同,其过程连接并打开数据库、处理事务和断开连接并关闭数据库构成:
1、连接并打开数据库。每个SQLite数据库都存储在单独的操作系统文件中,数据库与文件一一对应。连接并打开数据库的接口调用为sqlite3_open(),它用来打开一个数据库文件,该数据库文件中可以包含许多个关系表。该接口调用成功返回SQLITE_OK。
数据库打开成功。SQLite还可以创建内存数据库。如果你使用:memory:或一个空字符串做数据库名,数据库将在RAM中创建。内存数据库将只能被创建它的连接所存取,不能与其它连接共享。另外,内存数据库只能存活于连接期间,一旦连接关闭,数据库就将从内存中被删除。
2、处理事务。SQLite 是支持事务处理的。默认情况下,事务自动提交,也就是每一个SQL语句都在一个独立的事务下运行。任何SQL语句命令都在事务下执行。可以通过Begin、Commit和Rollback等命令手动提交事务。如开始、提交、回滚事务过程如下:
3、数据库SQL语句执行。在SQLite数据库中执行事务最常用的接口是sqlite3_exec(),在这个函数中有指向sqlite3_exec()的回调函数的指针参数。例如做 insert 操作或做 delete 操作时,就没有必要使用回调,该函数指针可设为NULL。而当你做 select 时,就要使用该回调函数,因为 sqlite3 把数据查出来,得通过回调告诉你查出了什么数据。
数据库对SQL语句的执行方式在下一节详述,回调函数的形式为:
typedef int (*sqlite3_callback)(void*,int,char**, char**)。
在SQLite数据库中执行事务的接口也可以是sqlite3_get_table(),它返回一个表格化的结果集。不需要提供回调函数。
4、执行SQL语句。SQL语句的执行过程由三个阶段完成,下面会详述。
5、格式化(动态构造)SQL语句,利用sqlite接口函数构造SQL语句,并调用相关接口执行语句。首先调用sqlite3_mprintf()或sqlite3_vprintf()格式化SQL语句,接着调用sqlite3_exec()执行语句,最后调用sqlite3_free()释放内存资源。也可以调用sqlite3_exec_printf()完成整个过程。
6、断开连接并关闭数据库。前面如果用 sqlite3_open 开启了一个数据库,结尾时不要忘了还要关闭所有附加的数据库文件。SQLite提供接口为SQLite3_close()。
SQL语句的执行在SQLite数据库中分两种情况,预编译查询和封装查询。
预处理查询是SQLite执行所有SQL命令的方式,每一个阶段都关联于语句句柄的一种状态(prepared、active和finalized)。Pepared表示所有资源都已分配,对应接口函数为sqlite3_prepare(),语句已经可以执行但还没有执行。现在还没有申请锁,一直到调用sqlite3_step()时才会申请锁。Active状态开始于对sqlite3_step()的调用,此时语句正在被执行并拥有某种锁。Finalized意味着语句已经被关闭且所有相关资源已经被释放。
封装查询是预处理查询的封装。在使用上比较简单,允许你在单一的函数调用中执行SQL命令。一个函数是sqlite3_exec(),特别适合执行不需要返回数据的查询。为了让查询结果数据返回,必须实现回调函数,传递给sqlite3_exec()函数作为参数。另一个是sqlite3_get_table(),返回一个表格化的结果集。封装查询也可以格式化SQL语句之后再执行。
二进制数据的数据库处理技术
在农业信息采集嵌入式系统中,为了满足对采集信息有效地在数据库中储存、管理、查询和传输的要求,必须要对数据库处理的关键技术进行研究。这些技术包括:记录和字符串处理、字段处理、错误控制、操作控制和线程处理。
1、记录和字符串的处理是数据库中最常用的处理方式。在前面也提到过sqlite3_exec()和sqlite3_get_table()函数是处理事务和执行SQL语句接口,区别在于sqlite3_exec()在处理记录,如执行SELECT时,要得到处理结果需提供回调函数。提供回调函数的作用就是当在执行完对记录的操作后,让回调函数按需要得到处理结果。字符串处理主要用在对SQL语句的格式化上,在SQLite数据库中常用接口为sqlite3_mprintf()或sqlite3_vprintf()。
2、字段处理是在记录操作的基础上进行的。在SQLite中提供了以对字段操作的函数接口,其特点是sqlite3_column_开头。这些接口可以获得字段名称、字段的存储类型和字段的值等信息。如获得一个字段的名称、储存类型和声明类型的函数调用如下:
3、SQLite数据库预定义了许多错误代码宏以方便程序设计错误处理的应用。很多API接口函数的返回类型是整形,这表示返回错误码,所以在接口调用中可以根据返回码进行错误处理,可以使用函数sqlite3_errmsg()获得附加的错误信息。
图像数据在sqlite数据库中是按照二进制形式存放的。 操作二进制数据需要用一个辅助的数据类型:sqlite3_stmt * 。它是一个已经把SQL语句进行了解析,并用sqlite自己标记记录的内部数据结构来表示的SQL语句。正因为这个结构已经被解析了,所以你可以往这个语句里插入二进制数据。
把二进制数据插到 sqlite3_stmt 结构的过程,必须用sqlite 提供的函数来插入。SQLite数据库提供了一种通配符机制用来表示SQL语句中不确定的字符值,这些通配符如?、aaa、nnn等。做这些通配符所代表的值在sqlite3_bind_开头的接口函数中被填充,在SQLite数据库中提供了很多以sqlite3_bind_开头的接口用来给SQL声明中的通配符赋值。
二进制数据的存储相对比较复杂一点,但从数据库对二进制数据的操作来看,主要分为数据写入和数据读出。