一、数据库基础概念
1.1 数据库分类
根据规模和应用场景,数据库可分为以下几类:
- 大型数据库:Oracle(适用于企业级高并发、大容量场景)
- 中型数据库:MySQL、MSSQL(适用于中小型系统、Web 应用)
- 小型数据库:SQLite、DB2(适用于嵌入式设备、轻量应用)
1.2 常用核心名词
缩写 | 全称 | 核心作用 |
---|---|---|
DB | Database(数据库) | 用于数据的存储、查询和更新,是数据的集合 |
DBMS | Database Management System(数据库管理系统) | 操作和管理数据库的软件,如 SQLite、MySQL |
MIS | Management Information System(管理信息系统) | 基于数据库的企业管理系统,如 ERP、CRM |
OA | Office Automation(办公自动化) | 基于数据库的协同办公系统,如考勤、审批 |
1.3 关系型数据库与 SQL 分类
关系型数据库基于表结构存储数据,通过SQL(Structured Query Language,结构化查询语言) 操作数据,SQL 按功能分为三类:
- DDL(数据定义语言):用于定义数据库结构,如建表、删表
- DML(数据操作语言):用于修改数据,如新增、更新、删除数据
- DQL(数据查询语言):用于查询数据,如条件查询、排序查询
二、SQLite 核心特性
SQLite 是轻量级嵌入式数据库,无需独立服务器,核心特点如下:
- 开源免费:基于 C 语言开发,源代码完全开放
- 极致轻量:核心代码仅约 1 万行,编译后体积小于 10MB
- 无需安装:绿色软件,解压即可使用,无复杂配置
- 文件存储:整个数据库存储在单一文件中,便于移动和备份
- 容量充足:最大支持 2TB 数据存储,满足中小型应用需求
- 跨平台兼容:支持 Windows、Linux、macOS 等主流操作系统
三、SQLite 安装与基本使用
3.1 安装方法(Ubuntu/Debian 系统)
# 安装SQLite命令行工具
sudo apt-get install sqlite3
# 安装开发库(含头文件和静态库,用于C语言开发)
sudo apt-get install libsqlite3-dev
验证安装
# 查看SQLite版本
sqlite3 --version
# 查看帮助信息
sqlite3 --help
编译 C 程序
# 编译时需链接SQLite库和线程库
gcc test.c -lsqlite3 -lpthread -o test
3.2 基本使用(命令行)
1. 启动与退出
# 打开或创建名为test.db的数据库文件(不存在则自动创建)
sqlite3 test.db
# 退出SQLite命令行(两种方式)
.q 或 .exit
- 成功启动后显示
sqlite>
提示符 - 若出现
...>
提示符,说明命令未结束,需输入;
结束
2. 创建数据库
# 方法1:先创建空文件,再打开
touch test.db
sqlite3 test.db
# 方法2:直接通过sqlite3命令创建并打开(推荐)
sqlite3 test.db
3.3 系统维护命令(以.
开头)
命令 | 功能描述 |
---|---|
.database | 列出当前数据库及关联文件路径 |
.tables | 列出当前数据库中的所有表 |
.schema [表名] | 显示指定表的结构(CREATE 语句),无表名则显示所有表 |
.dump [表名] | 导出数据库或指定表的 SQL 脚本 |
.headers on/off | 开启 / 关闭查询结果的列标题显示 |
.exit | 退出 SQLite 程序 |
3.4 数据库导入与导出
导出数据库(备份)
# 将test.db数据库导出为SQL脚本backup.sql
sqlite3 test.db .dump > backup.sql
导入数据库(恢复)
# 将backup.sql脚本导入到new.db数据库(new.db不存在则创建)
sqlite3 new.db < backup.sql
四、SQL 基本语法
4.1 DDL(数据定义语言)
1. 创建表
-- 方式1:默认字段类型为TEXT
CREATE TABLE user(id, name, age);
-- 方式2:指定字段类型(推荐)
CREATE TABLE user(
id INT, -- 整数类型
name TEXT, -- 文本类型
age INT, -- 整数类型
dt DATETIME -- 时间类型
);
- SQLite 支持的数据类型:
INT
(整数)、TEXT
(文本)、REAL
(浮点数)、BLOB
(二进制) - 若不指定类型,默认按
TEXT
处理
2. 删除表
-- 删除名为user的表(谨慎操作,数据不可恢复)
DROP TABLE user;
4.2 DML(数据操作语言)
1. 插入数据
-- 插入指定字段的数据(未指定字段值为NULL)
INSERT INTO user(id, age) VALUES(1, 10);
-- 插入完整记录(需与表字段顺序一致)
INSERT INTO user VALUES(3, "wang", 11, datetime('now', '+8 hours'));
-- 只插入部分字段(其余字段为NULL)
INSERT INTO user(age) VALUES(12);
datetime('now', '+8 hours')
:获取当前东八区时间
2. 更新数据
-- 单条件更新:修改name为'li'的记录的id为1
UPDATE user SET id = 1 WHERE name = 'li';
-- 多条件更新(AND):同时满足两个条件
UPDATE user SET id = 1 WHERE name = "li" AND passwd = "123";
-- 多条件更新(OR):满足任一条件
UPDATE user SET id = 2 WHERE name = "li" OR name = "zhao";
3. 删除数据
-- 删除表中所有数据(谨慎操作,无条件删除)
DELETE FROM user;
-- 单条件删除:删除id为1的记录
DELETE FROM user WHERE id = 1;
-- 多条件删除(AND/OR)
DELETE FROM user WHERE id = 1 AND name = "zhang";
DELETE FROM user WHERE id = 1 OR id = 2;
4.3 DQL(数据查询语言)
1. 基本查询
-- 查询表中所有字段和数据
SELECT * FROM user;
-- 查询指定字段
SELECT id FROM user;
SELECT id, name FROM user;
2. 条件查询
-- 逻辑条件查询(NOT):查询age不小于30的记录
SELECT * FROM user WHERE NOT age < 30;
-- 模糊查询(LIKE):%匹配0-任意字符,_匹配1个字符
SELECT * FROM user WHERE name LIKE '张%'; -- 匹配姓张的所有记录
SELECT * FROM user WHERE name LIKE '张_'; -- 匹配姓张且名字为2个字的记录
-- 排序查询(ORDER BY):ASC升序(默认),DESC降序
SELECT * FROM user ORDER BY id; -- 按id升序
SELECT * FROM user ORDER BY id DESC; -- 按id降序
-- 限制结果数量(LIMIT):只返回前2条记录
SELECT * FROM user LIMIT 2;
-- 组合查询:条件+排序+限制
SELECT * FROM user
WHERE age > 20 OR age < 50
ORDER BY age DESC
LIMIT 2;
4.4 高级特性:自动增长列
SQLite 通过INTEGER PRIMARY KEY
实现自动增长,无需AUTOINCREMENT
:
-- 创建含自动增长列的表
CREATE TABLE user3(
id INTEGER PRIMARY KEY ASC, -- ASC表示升序增长(默认)
name TEXT,
age INT,
dt DATETIME
);
-- 插入数据:id传入NULL触发自增(首条记录id=1,后续自动+1)
INSERT INTO user3 VALUES(NULL, '李四', 23, datetime('now'));
五、SQLite C 语言接口
5.1 开发环境准备
- 头文件:
#include <sqlite3.h>
- 编译命令:
gcc test.c -lsqlite3 -lpthread -o test
5.2 核心 API 函数
1. 打开数据库:sqlite3_open
int sqlite3_open(
const char *path, // 数据库文件路径(如"./test.db")
sqlite3 **db // 数据库连接句柄的指针(输出参数)
);
- 功能:打开指定路径的数据库文件,不存在则创建
- 返回值:成功返回
SQLITE_OK
(0),失败返回非 0 错误码 - 错误处理:通过
sqlite3_errmsg(db)
获取错误信息
2. 关闭数据库:sqlite3_close
int sqlite3_close(sqlite3 *db); // db:数据库连接句柄
- 功能:关闭数据库连接
- 返回值:成功返回
SQLITE_OK
,失败返回错误码 - 注意:关闭前需确保所有 SQL 操作已完成
3. 执行 SQL 语句:sqlite3_exec
int sqlite3_exec(
sqlite3 *db, // 数据库连接句柄
const char *sql, // 要执行的SQL语句
int (*callback)(void*,int,char**,char**), // 回调函数(处理查询结果)
void *arg, // 传递给回调函数的参数
char **errmsg // 错误信息指针(输出参数)
);
- 功能:执行 SQL 语句(INSERT/UPDATE/DELETE/SELECT 等)
- 回调函数:仅 SELECT 查询时需要,用于逐行处理结果;非查询语句可设为
NULL
- 错误处理:错误信息需通过
sqlite3_free(errmsg)
释放内存
5.3 回调函数定义
回调函数用于处理sqlite3_exec
执行 SELECT 后的查询结果:
// 回调函数:逐行处理查询结果
static int callback(
void *NotUsed, // 用户自定义参数(由sqlite3_exec的arg传入)
int argc, // 结果列数
char **argv, // 结果数据数组(argv[i]为第i列的值,NULL表示空值)
char **azColName // 列名数组(azColName[i]为第i列的列名)
) {
int i;
// 遍历列数据,打印列名和对应值
for (i = 0; i < argc; i++) {
printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
printf("\n"); // 每行数据后换行
return 0; // 返回0表示继续处理下一行,非0则中断
}
5.4 完整示例代码
示例 1:控制台输出查询结果
#include <stdio.h>
#include <sqlite3.h>
// 回调函数:处理并打印查询结果
int show(void* arg, int col, char** result, char** title) {
static int flag = 0; // 标记是否首次调用(仅打印一次列名)
int i = 0;
// 首次调用:打印列名
if (0 == flag) {
flag = 1;
for (i = 0; i < col; i++) {
printf("%s\t", title[i]);
}
}
// 打印当前行数据
printf("\n");
for (i = 0; i < col; i++) {
printf("%s\t", result[i] ? result[i] : "NULL");
}
return 0;
}
int main(int argc, char** argv) {
sqlite3* db = NULL; // 数据库连接句柄
char* errmsg = NULL; // 错误信息指针
int ret;
// 1. 打开数据库
ret = sqlite3_open("./test.db", &db);
if (SQLITE_OK != ret) {
fprintf(stderr, "打开数据库失败:%s\n", sqlite3_errstr(ret));
sqlite3_close(db);
return 1;
}
// 2. 执行查询SQL
char sql_cmd[] = "SELECT * FROM user;";
ret = sqlite3_exec(db, sql_cmd, show, NULL, &errmsg);
if (SQLITE_OK != ret) {
fprintf(stderr, "执行SQL失败:%s(SQL:%s)\n", errmsg, sql_cmd);
sqlite3_free(errmsg); // 释放错误信息内存
sqlite3_close(db);
return 1;
}
// 3. 关闭数据库
sqlite3_close(db);
return 0;
}
示例 2:查询结果写入文件
#include <stdio.h>
#include <sqlite3.h>
// 回调函数:将查询结果写入文件
int show(void* arg, int col, char** result, char** title) {
FILE* fp = (FILE*)arg; // 传入的文件指针
static int flag = 0; // 标记是否首次调用
int i = 0;
// 首次调用:写入列名
if (0 == flag) {
flag = 1;
for (i = 0; i < col; i++) {
fprintf(fp, "%s\t", title[i]);
}
}
// 写入当前行数据
fprintf(fp, "\n");
for (i = 0; i < col; i++) {
fprintf(fp, "%s\t", result[i] ? result[i] : "NULL");
}
return 0;
}
int main(int argc, char** argv) {
sqlite3* db = NULL;
char* errmsg = NULL;
int ret;
// 1. 打开数据库
ret = sqlite3_open("./test.db", &db);
if (SQLITE_OK != ret) {
fprintf(stderr, "打开数据库失败:%s\n", sqlite3_errstr(ret));
sqlite3_close(db);
return 1;
}
// 2. 打开文件(用于写入结果)
FILE* fp = fopen("result.txt", "w");
if (NULL == fp) {
perror("打开文件失败");
sqlite3_close(db);
return 1;
}
// 3. 执行查询SQL,将文件指针传入回调函数
char sql_cmd[] = "SELECT * FROM user;";
ret = sqlite3_exec(db, sql_cmd, show, fp, &errmsg);
if (SQLITE_OK != ret) {
fprintf(stderr, "执行SQL失败:%s(SQL:%s)\n", errmsg, sql_cmd);
sqlite3_free(errmsg);
sqlite3_close(db);
fclose(fp);
return 1;
}
// 4. 关闭资源
fclose(fp);
sqlite3_close(db);
return 0;
}
5.5 运行示例
# 1. 编译代码
gcc query_to_file.c -lsqlite3 -lpthread -o query_to_file
# 2. 执行程序(前提:test.db已存在且含user表)
./query_to_file
# 3. 查看结果文件
cat result.txt
理想输出(result.txt):
id name age dt
1 张三 23 2024-05-20 15:30:45
2 李四 25 2024-05-20 15:31:20