SQLite3 数据库学习笔记
一、SQL 语言概述
1.1 SQL 分类
-
DDL (Data Definition Language) - 数据定义语言
-
创建、修改、删除数据库对象(表、索引等)
-
命令:
CREATE,ALTER,DROP
-
-
DML (Data Manipulation Language) - 数据操作语言
-
插入、更新、删除表中的数据
-
命令:
INSERT,UPDATE,DELETE
-
-
DQL (Data Query Language) - 数据查询语言
-
查询表中的数据
-
命令:
SELECT
-
1.2 数据库分类
-
关系型数据库:SQLite, MySQL, Oracle, MSSQL
-
非关系型数据库:MongoDB, Redis
二、SQLite3 简介
2.1 特点
-
开源 - C语言开发
-
轻量级 - 代码约1万行,大小<10MB
-
绿色软件 - 无需安装,解压即用
-
文件型数据库 - 数据库存储在单个文件中
-
容量大 - 支持最大2TB数据
2.2 安装
# Ubuntu 安装
sudo apt-get install sqlite3
sudo apt-get install libsqlite3-dev
# 验证安装
sqlite3 --version
sqlite3 --help
2.3 编译选项
gcc program.c -lsqlite3 -lpthread
三、SQLite3 基本使用
3.1 启动和退出
# 启动数据库
sqlite3 database.db
# 退出数据库
sqlite> .quit 或 .q
# 退出续行模式
...> ;
3.2 系统维护命令(以.开头)
| 命令 | 功能 |
|---|---|
.help |
显示所有维护命令 |
.database |
显示当前数据库 |
.tables |
显示所有表 |
.schema 表名 |
显示表结构 |
.dump |
导出数据库 |
3.3 创建数据库
# 方法1
touch mydb.db
sqlite3 mydb.db
# 方法2
sqlite3 mydb.db
四、SQL 语句详解
4.1 DDL - 创建和删除表
-- 创建表(简单形式)
CREATE TABLE user(id, name, age);
-- 创建表(指定数据类型)
CREATE TABLE user(
id INTEGER,
name CHAR(50),
age INT
);
-- 创建表(带主键)
CREATE TABLE user(
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT,
age INTEGER
);
-- 删除表
DROP TABLE user;
数据类型:
-
INTEGER- 整型 -
TEXT- 文本 -
REAL- 浮点数 -
BLOB- 二进制数据
4.2 DML - 数据操作
4.2.1 插入数据
-- 插入完整记录
INSERT INTO user VALUES(1, '张三', 20);
-- 插入指定字段
INSERT INTO user (name, age) VALUES('李四', 22);
-- 插入多行
INSERT INTO user VALUES
(1, '张三', 20),
(2, '李四', 22);
4.2.2 更新数据
-- 更新所有记录
UPDATE user SET age = 25;
-- 条件更新
UPDATE user SET age = 30 WHERE name = '张三';
-- 多条件更新
UPDATE user SET age = 18
WHERE name = '张三' AND id = 1;
UPDATE user SET age = 20
WHERE name = '张三' OR name = '李四';
4.2.3 删除数据
-- 删除所有数据
DELETE FROM user;
-- 条件删除
DELETE FROM user WHERE id = 1;
-- 多条件删除
DELETE FROM user WHERE id = 1 AND name = '张三';
DELETE FROM user WHERE id = 1 OR id = 2;
4.3 DQL - 数据查询
4.3.1 基本查询
-- 查询所有字段
SELECT * FROM user;
-- 查询指定字段
SELECT name, age FROM user;
-- 条件查询
SELECT * FROM user WHERE age > 18;
-- 多条件查询
SELECT * FROM user
WHERE age > 18 AND name LIKE '张%';
SELECT * FROM user
WHERE age > 20 OR age < 15;
4.3.2 高级查询
-- LIKE 模糊查询
SELECT * FROM user WHERE name LIKE '张%'; -- 以张开头的
SELECT * FROM user WHERE name LIKE '%三'; -- 以三结尾的
SELECT * FROM user WHERE name LIKE '%三%'; -- 包含三的
-- 排序
SELECT * FROM user ORDER BY age; -- 升序
SELECT * FROM user ORDER BY age DESC; -- 降序
-- 限制结果数量
SELECT * FROM user LIMIT 5; -- 前5条
SELECT * FROM user LIMIT 5 OFFSET 10; -- 跳过10条取5条
-- 分组
SELECT age, COUNT(*) FROM user
GROUP BY age
HAVING COUNT(*) > 1;
4.4 日期时间处理
-- 创建带日期时间的表
CREATE TABLE user1(
id INTEGER,
name CHAR(50),
age INTEGER,
dt DATETIME
);
-- 插入当前时间
INSERT INTO user1 VALUES
(1, '张三', 23, datetime('now'));
-- 插入北京时间(东八区)
INSERT INTO user1 VALUES
(2, '李四', 24, datetime('now', '+8 hours'));
五、数据导入导出
5.1 导出数据库
sqlite3 mydb.db .dump > backup.sql
5.2 导入数据库
sqlite3 newdb.db < backup.sql
5.3 安装可视化工具
sudo apt-get install sqlitebrowser
六、SQLite3 C 语言编程接口
6.1 头文件和编译
#include <sqlite3.h>
// 编译
gcc program.c -lsqlite3 -lpthread
6.2 编程框架
-
打开数据库
-
执行SQL操作
-
关闭数据库
6.3 核心API函数
6.3.1 打开和关闭数据库
int sqlite3_open(const char *filename, sqlite3 **ppDb);
int sqlite3_close(sqlite3 *db);
示例:
sqlite3 *db;
int rc;
rc = sqlite3_open("test.db", &db);
if (rc) {
fprintf(stderr, "无法打开数据库: %s\n", sqlite3_errmsg(db));
return 1;
}
// ... 数据库操作 ...
sqlite3_close(db);
6.3.2 执行非查询语句(INSERT/UPDATE/DELETE)
int sqlite3_exec(
sqlite3 *db, // 数据库句柄
const char *sql, // SQL语句
sqlite3_callback callback, // 回调函数(查询时使用)
void *data, // 回调函数参数
char **errmsg // 错误信息
);
示例:
char *err_msg = 0;
char *sql = "INSERT INTO user VALUES(1, '张三', 20);";
int rc = sqlite3_exec(db, sql, 0, 0, &err_msg);
if (rc != SQLITE_OK) {
fprintf(stderr, "SQL错误: %s\n", err_msg);
sqlite3_free(err_msg);
}
6.3.3 执行查询语句
int sqlite3_get_table(
sqlite3 *db, // 数据库句柄
const char *sql, // SQL查询语句
char ***resultp, // 结果集
int *nrow, // 行数
int *ncol, // 列数
char **errmsg // 错误信息
);
void sqlite3_free_table(char **result);
示例:
char *err_msg = 0;
char **results = NULL;
int rows, columns;
char *sql = "SELECT * FROM user;";
int rc = sqlite3_get_table(db, sql, &results, &rows, &columns, &err_msg);
if (rc == SQLITE_OK) {
// 打印表头
for (int i = 0; i < columns; i++) {
printf("%s\t", results[i]);
}
printf("\n");
// 打印数据
for (int i = 1; i <= rows; i++) {
for (int j = 0; j < columns; j++) {
printf("%s\t", results[i * columns + j]);
}
printf("\n");
}
}
sqlite3_free_table(results);
6.3.4 回调函数方式查询
// 回调函数原型
typedef int (*sqlite3_callback)(
void *data, // sqlite3_exec 第4个参数
int argc, // 字段数
char **argv, // 字段值
char **azColName // 字段名
);
示例:
int callback(void *data, int argc, char **argv, char **azColName) {
for (int i = 0; i < argc; i++) {
printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
printf("\n");
return 0;
}
// 执行查询
char *sql = "SELECT * FROM user;";
int rc = sqlite3_exec(db, sql, callback, 0, &err_msg);
七、完整编程示例
7.1 学生信息管理系统
cpp
#include <stdio.h>
#include <sqlite3.h>
#include <string.h>
int main() {
sqlite3 *db;
char *err_msg = 0;
int rc;
// 1. 打开数据库
rc = sqlite3_open("student.db", &db);
if (rc != SQLITE_OK) {
fprintf(stderr, "无法打开数据库: %s\n", sqlite3_errmsg(db));
return 1;
}
// 2. 创建学生表
char *sql = "CREATE TABLE IF NOT EXISTS students("
"id INTEGER PRIMARY KEY AUTOINCREMENT,"
"name TEXT NOT NULL,"
"age INTEGER,"
"major TEXT,"
"phone TEXT,"
"gender TEXT,"
"create_time DATETIME DEFAULT CURRENT_TIMESTAMP);";
rc = sqlite3_exec(db, sql, 0, 0, &err_msg);
if (rc != SQLITE_OK) {
fprintf(stderr, "创建表失败: %s\n", err_msg);
sqlite3_free(err_msg);
}
// 3. 插入学生数据
sql = "INSERT INTO students (name, age, major, phone, gender) VALUES"
"('张三', 20, '电信', '1101010010', '男'),"
"('李四', 22, '测控', '1201010011', '女'),"
"('王五', 19, '计算机', '1301010012', '男');";
rc = sqlite3_exec(db, sql, 0, 0, &err_msg);
if (rc != SQLITE_OK) {
fprintf(stderr, "插入数据失败: %s\n", err_msg);
sqlite3_free(err_msg);
}
// 4. 查询回调函数
int print_callback(void *data, int argc, char **argv, char **azColName) {
for (int i = 0; i < argc; i++) {
printf("%-15s: %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
printf("----------------------------------------\n");
return 0;
}
// 5. 查询所有学生
printf("所有学生信息:\n");
printf("========================================\n");
sql = "SELECT * FROM students;";
rc = sqlite3_exec(db, sql, print_callback, 0, &err_msg);
if (rc != SQLITE_OK) {
fprintf(stderr, "查询失败: %s\n", err_msg);
sqlite3_free(err_msg);
}
// 6. 修改数据
sql = "UPDATE students SET age = 21 WHERE name = '张三';";
rc = sqlite3_exec(db, sql, 0, 0, &err_msg);
// 7. 删除数据
sql = "DELETE FROM students WHERE age < 20;";
rc = sqlite3_exec(db, sql, 0, 0, &err_msg);
// 8. 关闭数据库
sqlite3_close(db);
printf("操作完成!\n");
return 0;
}
7.2 编译和运行
gcc student_system.c -o student_system -lsqlite3
./student_system
八、实用技巧
8.1 创建成绩表
-- 学生表
CREATE TABLE stu_info(
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
age INTEGER,
phone TEXT,
email TEXT,
qq TEXT
);
-- 成绩表
CREATE TABLE scores(
id INTEGER PRIMARY KEY AUTOINCREMENT,
stu_id INTEGER,
subject TEXT,
score REAL,
exam_date DATE,
FOREIGN KEY (stu_id) REFERENCES stu_info(id)
);
8.2 复杂查询示例
-- 查询成绩及学生信息
SELECT s.name, sc.subject, sc.score
FROM stu_info s
JOIN scores sc ON s.id = sc.stu_id
WHERE sc.score > 60
ORDER BY sc.score DESC;
-- 统计每个学生的平均分
SELECT s.name, AVG(sc.score) as avg_score
FROM stu_info s
JOIN scores sc ON s.id = sc.stu_id
GROUP BY s.id
HAVING avg_score > 70;
8.3 事务处理
// 开始事务
sqlite3_exec(db, "BEGIN TRANSACTION", 0, 0, 0);
// 执行多个SQL操作
sqlite3_exec(db, "INSERT INTO ...", 0, 0, 0);
sqlite3_exec(db, "UPDATE ...", 0, 0, 0);
// 提交事务
sqlite3_exec(db, "COMMIT", 0, 0, 0);
// 出错时回滚
sqlite3_exec(db, "ROLLBACK", 0, 0, 0);
九、常见问题解决
-
数据库被锁:检查是否有其他进程正在使用数据库
-
中文乱码:确保使用UTF-8编码
-
内存泄漏 :确保释放
sqlite3_free()和sqlite3_free_table() -
并发访问:使用SQLite的WAL模式提高并发性能
十、最佳实践
-
始终检查返回值:每个SQLite API调用都应检查返回值
-
使用预处理语句 :对于频繁执行的SQL,使用
sqlite3_prepare_v2() -
错误处理:妥善处理错误信息并释放资源
-
关闭连接:确保在所有路径上都关闭数据库连接
-
备份数据 :定期使用
.dump命令备份数据库