赞
踩
对于MySQL、SQL Server或Oracle等数据库,大家都耳熟能详,但实际上使用最为广泛的数据库引擎却是SQLite,手机、电脑、汽车、ATM机等许许多多的设备中,包括很多的应用程序中(例如微信)都内置了SQLite,这得益于它小型、 快速、 自包含、 高可靠性、 全功能的特性。
SQLite是一个嵌入式的关系型数据库引擎,其他关系型数据库一般是client/server架构的,需要安装、启动服务、占用端口,客户端通过特定的协议比如JDBC/ODBC与数据库服务器通信,数据库服务器通过监听某个Socket端口去接收客户端的查询请求,之后将结果返回给客户端。SQLite的数据库就是一个独立的文件,所有的结构定义、表、索引和数据本身都在这个文件里,所以它很容易跨平台使用,并且它依然支持关系型数据库的关键特性,SQLite通过In-Process的方式来与应用程序通信的,当应用程序发出查询请求时,这些请求是通过函数调用的方式在与应用程序相同的线程内执行的,没有其他数据库网络通信的开销,与其他数据库相比,SQLite的优势就是快。
同时,SQLIte罕见的做到了100%测试覆盖,它的源码只有15多万行,但其测试代码有九千多万行,测试用例惊人地达到了10万个,在多种芯片、多种操作系统中完整测试一遍将会产生 10 亿次测试,这保证了sqlite的高可靠性和稳定性。开发者若是想使用 SQL 在文件中存储结构化的数据,应该重点考虑SQLite。
在linux系统中,使用apt-get即可安装:
- apt-get install libsqlite3-dev
- apt-get install sqlite3
一般在代码中使用sqlite,只安装libsqlite3-dev即可,若安装失败,apt-get update后再次安装。
也可去官方网站下载SQLite Download Page
SQLite对数据库进行操作使用SQL语言,不区分大小写。
首先需要头文件:
#include <sqlite3.h>
打开或者创建数据库使用sqlite3_open接口, 若数据库不存在,则创建后打开,若存在,直接打开,用sqlite3* 类型的变量接收操作句柄,返回值不等于SQLITE_OK,代表失败,sqlite3_errmsg可获得具体错误信息。
- string dir = "/***/***/sqlite_db.db";
- sqlite3* db;
- int rc = sqlite3_open(dir.c_str(), &db);
- if (rc != SQLITE_OK) {
- cout << "[Sqlite] Open DB Failed!, Detail:" << sqlite3_errmsg(db_);
- db_ = nullptr;
- }
对数据库进行任何操作,都可使用sqlite3_exec接口:
- int sqlite3_exec(
- sqlite3*, /* 数据库 */
- const char *sql, /* 要计算的 SQL */
- int (*callback)(void*,int,char**,char**), /* 回调函数 */
- void *, /* 回调的第一个参数 */
- char **errmsg /* 错误信息写在这里 */ );
创建表一般情况下不需要回调函数,只需要准备好对应的SQL语句即可, 推荐使用Create Table If Not Exist语句,只会在表不存时进行创建;其中,a\b\c\d 代指列名,后接数据类型,具体语法参考官方网站Query Language Understood by SQLite
- char *err_msg = nullptr;
- char sql[kMaxSqlLength];
- string name = "test"; //表名
- sprintf(sql,
- "Create Table If Not Exists %s( a int, b text primary key not null, \
- c int, d integer);",
- name.c_str());
- auto rc = sqlite3_exec(db, sql, NULL, 0, &err_msg);
- if (rc != SQLITE_OK) {
- cout << "[Sqlite] Create Table Failed, Detail:" << err_msg << ", sql:" << sql;
- sqlite3_free(err_msg);
- }
同样使用sqlite3_exec接口,但需要有回调函数来接收读取到的数据,值得注意的是:每读取一行,回调函数都会被调用一次。
- int selectDataCallback(void *data, int argc, char **argv, char **azColName)
- {
- //data, 由外部传人用来接收数据
- //argc, 列数
- //argv, 数据
- //azColName, 列名,argv和azColName用argc作为下标可取出每一列的列名和数据
- return 0;
- };
-
- char sql[kMaxSqlLength];
- sprintf(sql, "select * from %s;", name.c_str());
- int rc = sqlite3_exec(
- db, sql, SelectDataCallBack, reinterpret_cast<void *>(data), &err_msg);
- if (rc != SQLITE_OK) {
- cout << "[Sqlite Error] Select Failed! Detail:" << err_msg << ", sql:" << sql;
- sqlite3_free(err_msg);
- }
对于插入,修改,删除等写入操作,同样使用qlite3_exec接口,一般情况也是不需要回调函数,使用正确的insert\update\delete SQL语句即可。
- char sql[kMaxSqlLength];
- char *err_msg = nullptr;
- sprintf(sql, "insert into %s values(%d, \'%s\', %d, %lu);",
- name_.c_str(), a, b.c_str(),c,d);
- int rc = sqlite3_exec(db, sql, NULL, NULL, &err_msg);
- if (rc != SQLITE_OK) {
- cout << "[Sqlite Error] insert Failed! Detail:" << err_msg << ", sql:" << sql;
- sqlite3_free(err_msg);
- }
SQLite支持三种不同的线程模式:
1、单线程。在此模式下,所有互斥锁都被禁用,并且SQLite一次不能在多个线程中使用。
2、多线程。在这种模式下,只要在两个或多个线程中不同时使用单个数据库连接,SQLite就可以被多个线程安全地使用。只要一个数据库连接不被多个线程同时使用就是安全的。
3、序列化(也有翻译成串行的)。在序列化模式下,启用所有的锁,SQLite可以被多个线程安全地使用而没有任何限制。
使用过程中可使用sqlite3_threadsafe()接口来判断是否线程安全,单线程模式返回false,其余两种模式返回True.
参考
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。