目录
[1. SQLite介绍](#1. SQLite介绍)
[2. ubuntu下SQLite命令行和开发库安装](#2. ubuntu下SQLite命令行和开发库安装)
[3. 终端使用介绍](#3. 终端使用介绍)
[3.1 常用命令](#3.1 常用命令)
[3.2 使用演示](#3.2 使用演示)
[4. 常用api介绍](#4. 常用api介绍)
[5. 使用案例](#5. 使用案例)
1. SQLite介绍
SQLite官网:SQLite Home Page
SQLite菜鸟教程:SQLite 数据类型 | 菜鸟教程
SQLite是一个开源、轻量级、零配置、无服务器、自包含、事务性、支持标准SQL、跨平台的数据库管理系统。
- 开源:免费使用,源码透明
- 轻量级:整个库非常小,编译之后仅需几百KB
- 零配置:无需安装、启动、停止或配置任何数据库服务器进程
- 无服务器:SQLite没有独立的服务器进程,应用程序直接通过函数调用读写磁盘上的数据库文件
- 自包含:整个数据库就是一个独立的、跨平台的单个文件(通常是.db后缀),文件中包含所有表、索引、数据和元信息
- 事务性:完全支持ACID(原子性、一致性、隔离性、持久性)事务,即使系统崩溃或断电也嗯呢保证数据完整性
- 支持标准SQL:它使用SQL语句来管理和查询数据,最多支持128TB
- 跨平台:数据库文件跨平台
- 简单易用:只需包含一个sqlite3.h和一个库文件即可
一般常用于嵌入式系统、移动开发中。
2. ubuntu下SQLite命令行和开发库安装
bash
> sudo apt install sqlite3 # 安装 sqlite3 命令⾏⼯具
> sudo apt install libsqlite3-dev # 安装 sqlite 开发包
> dpkg -L libsqlite3-dev # 列出已安装的 libsqlite3-dev 软件包所包含的所有⽂件及其安
装路径
/.
/usr
/usr/include
/usr/include/sqlite3.h
/usr/include/sqlite3ext.h
/usr/lib
/usr/lib/x86_64-linux-gnu
/usr/lib/x86_64-linux-gnu/libsqlite3.a
/usr/lib/x86_64-linux-gnu/pkgconfig
/usr/lib/x86_64-linux-gnu/pkgconfig/sqlite3.pc
/usr/share
/usr/share/doc
/usr/share/doc/libsqlite3-dev
/usr/share/doc/libsqlite3-dev/copyright
/usr/lib/x86_64-linux-gnu/libsqlite3.so
/usr/share/doc/libsqlite3-dev/changelog.Debian.gz
编译时链接sqlite3库
bash
makefile⽂件:
g++ main.cpp -o my_program -lsqlite3
CMakelists.txt:
target_link_libraries(${SDK_NAME} sqlite3)
3. 终端使用介绍
3.1 常用命令
数据库操作命令:
|------------------|------------|-------------------------------|
| 命令 | 说明 | 示例 |
| .open ⽂件名 | 打开或创建数据库⽂件 | .open student.db |
| .databases | 显示所有连接的数据库 | .databases |
| .attach ⽂件 as 别名 | 附加另⼀个数据库 | .attach archive.db as archive |
| .backup ⽂件名 | 备份当前数据库 | .backup backup.db |
| .restore ⽂件名 | 从备份恢复数据库 | .restore recovery.db |
| .quit | 退出SQLite | .quit |
| .exit | 退出SQLite | .exit |
| .help | 显示帮助信息 | .help |
表和结构命令:
|-----------------|--------|-------------------|
| 命令 | 说明 | 示例 |
| .tables | 显示所有表 | .tables |
| .schema [表名] | 显示表结构 | .schema students |
| .indexes [表名] | 显示索引 | .indexes students |
3.2 使用演示
sql
> sqlite3 # 打开 sqlite 命令⾏⼯具
sqlite> .help # 查看帮助信息
sqlite> .open student.db # 创建student数据库,数据库⽂件名称为student.db
sqlite> .databases # 验证数据库。检查当前连接了哪些数据库,以及数据库的详细状态
信息
sqlite> .tables # 查看所有表
sqlite> CREATE TABLE students( #创建学⽣表
(x1...> id INTEGER PRIMARY KEY AUTOINCREMENT,
(x1...> name TEXT NOT NULL,
(x1...> age INTEGER,
(x1...> score REAL
(x1...> );
sqlite> .schema students # 查看表结构
sqlite> INSERT INTO students(name, age, score) VALUES # students中插⼊数据
...> ('张三', 18, 92.0),
...> ('李四', 19, 93.5),
...> ('王五', 18, 76.5);
sqlite> SELECT * FROM students; # 查看学⽣信息
1|张三|18|92.0
2|李四|19|93.5
3|王五|18|76.5
sqlite> DELETE FROM students WHERE score < 80; # 删除成绩⼩于80分同学信息
sqlite> SELECT * FROM students;
1|张三|18|92.0
2|李四|19|93.5
4. 常用api介绍
sql
数据库连接管理:
int sqlite3_open(const char *filename, sqlite3 **ppDb);
功能:打开⼀个数据库连接。如果数据库⽂件不存在,则创建它
参数:filename - 数据库⽂件的路径,
ppDb:⼀个指向sqlite3*的指针。函数成功后会在这个指针⾥填⼊数据库连接句柄
返回值:SQLITE_OK 表⽰创建成功,否则为错误码
int sqlite3_close(sqlite3* db);
功能:关闭打开的数据库连接,并释放所有资源
参数:要关闭的数据库连接句柄
返回值:SQLITE_OK表⽰成功,如果还有未完成的预处理语句
const char *sqlite3_errmsg(sqlite3* db);
功能:获取与数据库连接相关的最后⼀次错误操作的英⽂描述字符串。在操作失败后调⽤它来获取错误
原因
参数:db数据库连接句柄
返回值:只想错误信息字符串的指针。如果还有查询没有完成,将返回SQLITE_BUSY禁⽌关闭的错误消息
执⾏SQL语句
int sqlite3_prepare_v2( sqlite3 *db,const char *zSql,int nByte,sqlite3_stmt **ppStmt,const char **pzTail);
功能:将⼀条SQL语句编译成⼀个预处理语句对象,为执⾏和绑定参数做准备
参数:db - 数据库连接句柄
zSql:要编译的SQL语句⽂本
nByte:SQL⽂本的⻓度(字节),-1表⽰⾃动计算到\0结束
ppStmt:指向sqlite3_stmt*的指针,表⽰输出预处理结果语句的句柄
pzTail:指向未使⽤的SQL部分指针,通常置为NULL
返回值:编译成功返回SQLITE_K,否则返回错误码
int sqlite3_bind_int64(sqlite3_stmt*, int index, sqlite3_int64 value);
功能:向预处理语句中的指定参数位置绑定⼀个64位的整数值
参数:index - 参数的序号,从1开始
value - 要绑定的整数值
返回值:SQLITE_OK表⽰绑定成功,否则为错误码
int sqlite3_bind_text(sqlite3_stmt*, int index, const char *value, int len,
void(*destructor)(void*));
功能:向预处理语句的指定参数位置绑定⼀个⽂本字符串
参数: index - 参数的序号,从1开始
value - 要绑定的⽂本字符串
len - 字符串的⻓度(字节),-1表⽰⾃动计算到\0结束
destructor:⽤于指定SQLite不会尝试释放该字符串
SQLITE_STATIC:SQLite不会尝试释放该字符串
SQLITE_TRANSIENT:SQLite会制作该字符串的副本
返回值:SQLITE_OK表⽰绑定成功,否则为错误码
int sqlite3_exec(sqlite3* db, const char *sql,int (*callback)(void*, int, char**, char**),void *arg,char **errmsg);
功能:执⾏⼀条或多条SQL语句,适合不返回数据的语句,如CREATE、INSERT
参数:db - 数据库连接句柄
sql - 要执⾏的SQL语句字符串
callback:回调函数,每有⼀条结果记录就产⽣⼀次调⽤,可以设置为NULL
arg:传递给回调函数的第⼀个参数
errmsg:只想错误信息的指针。必须⽤sqlite3_free释放
返回值:执⾏成功返回SQLITE_OK,否则返回错误码
int sqlite3_step(sqlite3_stmt *pStmt);
功能:⽤于逐步执⾏预处理语句。⼀般⽤于执⾏查询和更新操作,并返回执⾏结果。对于查询操作,
sqlite3_step 需要多次调⽤,直到返回 SQLITE_DONE
参数:pstmt - 预处理语句句柄
返回值: SQLITE_ROW - 表⽰有⼀⾏结果数据就绪
SQLITE_DONE - 表⽰语句执⾏完成
否则表⽰有其他错误
const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
功能:从当前结果⾏中,以const unsigned cht*的形式获取制定⽂本列的值
参数:iCol表⽰列号,从0开始
返回值:指向⽂本数据的指针。
int sqlite3_finalize(sqlite3_stmt *pStmt);
功能:销毁预处理语句对象,释放所有关联资源
参数:pstmt - 要销毁的预处理语句句柄
返回值:成功返回SQLITE_OK,否则为错误码
5. 使用案例
下面持久化存储学生信息,学生基本信息包括学号、姓名、性别、年龄、学分
cpp
#include <iostream>
using namespace std;
#include <sqlite3.h>
struct StudentInfo
{
StudentInfo(const std::string &name, const std::string &gender, int age,
double gap)
: name(name), gender(gender), age(age), gap(gap)
{
}
std::string name;
std::string gender;
int age;
double gap;
};
class StudentDB
{
public:
StudentDB(const std::string &dbName)
{
// 创建数据库
if (SQLITE_OK != sqlite3_open("student.db", &_db))
{
std::cout << "open student.db failed" << std::endl;
exit(-1);
}
// 对数据库初始化 - 创建学⽣表
if (!initDataBase())
{
std::cout << "init database failed" << std::endl;
exit(-1);
}
}
~StudentDB()
{
if (_db)
{
sqlite3_close(_db);
_db = nullptr;
}
}
bool
insertStudentInfo(const StudentInfo &info)
{
// 构建sql语句
std::string sql = "INSERT INTO student(name, gender, age, gap)"
"VALUES(?, ?, ?, ?);";
// 准备SQL语句
sqlite3_stmt *stmt = nullptr;
if (SQLITE_OK != sqlite3_prepare_v2(_db, sql.c_str(), -1, &stmt,
nullptr))
{
std::cout << "prepare sql failed: " << sqlite3_errmsg(_db) << std::endl;
return false;
}
// 绑定参数 sqlite3_bind_text(stmt, 1, info.name.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, info.gender.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 3, info.age);
sqlite3_bind_double(stmt, 4, info.gap);
// 执⾏SQL语句,检查是否执⾏成功
if (SQLITE_DONE != sqlite3_step(stmt))
{
std::cout << "execute sql failed: " << sqlite3_errmsg(_db) << std::endl;
sqlite3_finalize(stmt);
return false;
}
// 执⾏完sql,释放stmt
sqlite3_finalize(stmt);
std::cout << "insert student info success" << std::endl;
return true;
}
bool
queryStudentInfo(const std::string &name)
{
// 构建sql语句
std::string sql = "SELECT * FROM student WHERE name = ?";
// 准备SQL语句
sqlite3_stmt *stmt = nullptr;
if (SQLITE_OK != sqlite3_prepare_v2(_db, sql.c_str(), -1, &stmt, nullptr))
{
std::cout << "prepare sql failed: " << sqlite3_errmsg(_db) << std::endl;
return false;
}
// 绑定参数 sqlite3_bind_text(stmt, 1, name.c_str(), -1, SQLITE_TRANSIENT);
// 执⾏SQL语句,检查是否执⾏成功
int result = sqlite3_step(stmt);
if (SQLITE_ROW != result && SQLITE_DONE != result)
{
std::cout << "execute sql failed: " << sqlite3_errmsg(_db) << std::endl;
sqlite3_finalize(stmt);
return false;
}
// 执⾏完sql,释放stmt sqlite3_finalize(stmt);
std::cout << "query student info success" << std::endl;
return true;
}
bool queryAllStudentInfo()
{
// 构建sql语句
std::string sql = "SELECT * FROM student";
// 准备SQL语句
sqlite3_stmt *stmt = nullptr;
if (SQLITE_OK != sqlite3_prepare_v2(_db, sql.c_str(), -1, &stmt,
nullptr))
{
std::cout << "prepare sql failed: " << sqlite3_errmsg(_db) << std::endl;
return false;
}
// 执⾏SQL语句,检查是否执⾏成功
int result = sqlite3_step(stmt);
if (SQLITE_ROW != result && SQLITE_DONE != result)
{
std::cout << "execute sql failed: " << sqlite3_errmsg(_db) << std::endl;
sqlite3_finalize(stmt);
return false;
}
std::cout
<< "-------------------student table info:-----------------"
<< std::endl;
// 遍历结果集
while (SQLITE_ROW == result)
{
// 表结构是 id, name, gender, age, gap,所以列索引从1开始获取我们需要的值
std::string name(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1)));
std::string gender(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 2)));
int age = sqlite3_column_int(stmt, 3);
double gap = sqlite3_column_double(stmt, 4);
std::cout << "name: " << name << ", gender: " << gender << ", age:" << age << ",gap : " << gap << std::endl;
result = sqlite3_step(stmt);
}
// 检查是否还有更多的⾏ if (SQLITE_DONE != result)
{
std::cout << "execute sql failed: " << sqlite3_errmsg(_db) << std::endl;
return false;
}
std::cout << "-------------------student table info end-----------------"<< std::endl;
// 执⾏完sql,释放stmt
sqlite3_finalize(stmt);
std::cout << "query all student info success" << std::endl;
return true;
}
// 修改学⽣信息
bool updateStudentInfo(const std::string &name, const StudentInfo &info)
{
// 构建sql语句
std::string sql = "UPDATE student SET name = ?, gender = ?, age = ?,gap =? WHERE name = ? ";
// 准备SQL语句
sqlite3_stmt *stmt = nullptr;
if (SQLITE_OK != sqlite3_prepare_v2(_db, sql.c_str(), -1, &stmt,
nullptr))
{
std::cout << "prepare sql failed: " << sqlite3_errmsg(_db) << std::endl;
return false;
}
// 绑定参数 sqlite3_bind_text(stmt, 1, info.name.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, info.gender.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 3, info.age);
sqlite3_bind_double(stmt, 4, info.gap);
sqlite3_bind_text(stmt, 5, name.c_str(), -1, SQLITE_TRANSIENT);
// 执⾏SQL语句,检查是否执⾏成功
if (SQLITE_DONE != sqlite3_step(stmt))
{
std::cout << "execute sql failed: " << sqlite3_errmsg(_db) << std::endl;
sqlite3_finalize(stmt);
return false;
}
// 执⾏完sql,释放stmt sqlite3_finalize(stmt);
std::cout << "update student info success" << std::endl;
return true;
}
// 删除学⽣信息
bool deleteStudentInfo(const std::string &name)
{
// 构建sql语句
std::string sql = "DELETE FROM student WHERE name = ?";
// 准备SQL语句
sqlite3_stmt *stmt = nullptr;
if (SQLITE_OK != sqlite3_prepare_v2(_db, sql.c_str(), -1, &stmt,
nullptr))
{
std::cout << "prepare sql failed: " << sqlite3_errmsg(_db) << std::endl;
return false;
}
// 绑定参数 sqlite3_bind_text(stmt, 1, name.c_str(), -1, SQLITE_TRANSIENT);
// 执⾏SQL语句,检查是否执⾏成功
if (SQLITE_DONE != sqlite3_step(stmt))
{
std::cout << "execute sql failed: " << sqlite3_errmsg(_db) << std::endl;
sqlite3_finalize(stmt);
return false;
}
// 执⾏完sql,释放stmt sqlite3_finalize(stmt);
std::cout << "delete student info success" << std::endl;
return true;
}
private:
bool initDataBase()
{
// 创建数据库表
const std::string studentTab = "CREATE TABLE IF NOT EXISTS student( "
"id INTEGER PRIMARY KEY, "
"name TEXT NOT NULL, "
"gender TEXT NOT NULL, "
"age INTEGER NOT NULL, "
"gap REAL NOT NULL)";
char *errMsg = nullptr;
if (SQLITE_OK != sqlite3_exec(_db, studentTab.c_str(), nullptr,
nullptr, &errMsg))
{
std::cout << "create table failed: " << errMsg << std::endl;
sqlite3_free(errMsg);
return false;
}
std::cout
<< "create studentTab success" << std::endl;
return true;
}
private:
sqlite3 *_db;
};
int main()
{
StudentInfo info1("张三", "男", 18, 3.5);
StudentInfo info2("李四", "男", 19, 3.8);
StudentInfo info3("王五", "男", 20, 2.9);
StudentInfo info4("赵六", "⼥", 21, 3.0);
StudentDB db("student.db");
db.insertStudentInfo(info1);
db.insertStudentInfo(info2);
db.insertStudentInfo(info3);
db.insertStudentInfo(info4);
db.queryAllStudentInfo();
info1.age = 20;
db.updateStudentInfo("张三", info1);
db.queryAllStudentInfo();
db.deleteStudentInfo("张三");
db.queryAllStudentInfo();
return 0;
}
运行程序,会在当前目录下生成一个student.db的数据库文件,里面存储表结构和数据信息。
bash
bit@bit08:~/will/test-cpp-proj/testsqlite3$ g++ testSQLite.cpp -o testsqlite3 -
lsqlite3
bit@bit08:~/will/test-cpp-proj/testsqlite3$ ./testsqlite3
create studentTab success
insert student info success
insert student info success
insert student info success
insert student info success
-------------------student table info:-----------------
name: 张三, gender: 男, age: 18, gap: 3.5
name: 李四, gender: 男, age: 19, gap: 3.8
name: 王五, gender: 男, age: 20, gap: 2.9
name: 赵六, gender: ⼥, age: 21, gap: 3
-------------------student table info end-----------------
query all student info success
update student info success
-------------------student table info:-----------------
name: 张三, gender: 男, age: 20, gap: 3.5
name: 李四, gender: 男, age: 19, gap: 3.8
name: 王五, gender: 男, age: 20, gap: 2.9
name: 赵六, gender: ⼥, age: 21, gap: 3
-------------------student table info end-----------------
query all student info success
delete student info success
-------------------student table info:-----------------
name: 李四, gender: 男, age: 19, gap: 3.8
name: 王五, gender: 男, age: 20, gap: 2.9
name: 赵六, gender: ⼥, age: 21, gap: 3
-------------------student table info end-----------------
query all student info success