一、数据库概述
1.1 数据库的定义与作用
数据库(Database)是一种按照数据结构来组织、存储和管理数据的软件系统。它能够高效地处理大批量数据,提供数据持久化、快速检索、并发控制、安全性保障等功能,是应用程序与数据之间的桥梁。
1.2 数据库的分类
根据数据组织方式,数据库主要分为两类:
-
关系型数据库:基于关系模型,使用表格(二维表)存储数据,表与表之间通过外键等约束建立关联。常见的有:
-
Oracle:大型企业级数据库,功能强大但资源占用高。
-
MySQL:开源广泛使用,适用于Web应用。
-
SQL Server:微软产品,与.NET生态集成良好。
-
SQLite:轻量级嵌入式数据库,无需独立服务进程,直接集成到应用程序中。
-
-
非关系型数据库:以键值对、文档、列族或图结构存储数据,适用于高并发、海量数据的场景。如Redis(键值存储)、MongoDB(文档型)等。
本次学习主要围绕SQLite展开,因为它轻巧、无需配置、支持标准SQL,非常适合嵌入式设备和桌面应用开发。
二、SQLite数据库基础
2.1 SQLite的特点
-
零配置:不需要安装和配置服务器,数据库就是一个单一的文件。
-
跨平台:支持Windows、Linux、macOS等多种操作系统。
-
轻量级:代码库小(约250KB),内存占用低。
-
支持SQL:实现了大部分SQL-92标准,支持事务(ACID)。
-
C语言接口:提供原生C API,便于嵌入式开发。
2.2 SQLite的安装(Ubuntu环境)
在Linux系统中,通过apt-get工具集安装SQLite及相关开发包:
sudo apt-get install sqlite3 # SQLite命令行工具
sudo apt-get install libsqlite3-dev # SQLite开发库(供C语言调用)
sudo apt-get install sqlitebrowser # 图形化管理工具(可选)
安装完成后,终端输入sqlite3即可进入交互式命令行环境。
2.3 SQLite常用命令
在sqlite3提示符下,以点号开头的命令用于管理数据库,常见的有:
| 命令 | 功能 |
|---|---|
.databases |
列出当前打开的数据库文件 |
.tables |
显示所有表名 |
.header on/off |
开启/关闭查询结果头部显示 |
.mode MODE |
设置输出格式,如csv、column、list等 |
.schema [表名] |
显示创建表的SQL语句 |
.quit |
退出sqlite3 |
例如,设置列对齐显示:
sqlite> .header on
sqlite> .mode column
三、SQL语句详解
SQL(Structured Query Language)是操作关系型数据库的标准语言。以下通过一个学生信息表student来演示常用操作。
3.1 数据定义语言(DDL)
创建表
CREATE TABLE student (
学号 INTEGER PRIMARY KEY,
姓名 TEXT,
性别 TEXT,
年龄 INTEGER,
成绩 INTEGER
);
-
PRIMARY KEY约束指定学号为主键,唯一标识一条记录。 -
SQLite支持的数据类型:
INTEGER、REAL、TEXT(实际上SQLite采用动态类型,但建议明确声明)。
删除表
DROP TABLE student;
3.2 数据操作语言(DML)
插入数据
-
全字段插入:
INSERT INTO student VALUES (1002, '李四', '女', 13, 80); -
部分字段插入:
INSERT INTO student (学号, 姓名, 性别) VALUES (1009, '熊大', '男');
删除数据
DELETE FROM student WHERE 姓名 = '赵五';
更新数据
UPDATE student SET 年龄 = 16, 成绩 = 85 WHERE 姓名 = '熊大';
3.3 数据查询语言(DQL)
基本查询
SELECT * FROM student; -- 查询所有列
SELECT 学号, 成绩 FROM student; -- 查询指定列
SELECT 姓名 FROM student WHERE 成绩 < 60 AND 性别 = '男'; -- 带条件查询
SELECT 姓名 FROM student WHERE 姓名 LIKE '%田%'; -- 模糊查询
排序
SELECT 学号, 姓名 FROM student WHERE 成绩 > 60 ORDER BY 成绩 DESC; -- 降序
SELECT 学号, 姓名 FROM student WHERE 成绩 > 60 ORDER BY 成绩 ASC; -- 升序
3.4 多表联合查询
实际应用中数据往往分散在多个表中,需要通过连接(JOIN)获取完整信息。假设有以下三表:
-
学生信息表:
学生信息(学号, 姓名, ...) -
课程表:
学生课程(编号, 名称) -
成绩表:
学生成绩(学号, 课程编号, 成绩)
交叉连接(CROSS JOIN)
返回两表的笛卡尔积,较少使用。
SELECT 学生信息.姓名 AS 姓名, 学生课程.名称 AS 课程
FROM 学生信息 CROSS JOIN 学生课程;
内连接(INNER JOIN)
返回两表中满足连接条件的记录。
SELECT 学生信息.姓名 AS 姓名, 学生成绩.成绩 AS 成绩
FROM 学生信息 INNER JOIN 学生成绩 ON 学生信息.学号 = 学生成绩.学号;
左外连接(LEFT OUTER JOIN)
返回左表全部记录,右表无匹配时填充NULL。
SELECT 学生信息.姓名 AS 姓名, 学生成绩.成绩 AS 成绩
FROM 学生信息 LEFT OUTER JOIN 学生成绩 ON 学生信息.学号 = 学生成绩.学号;
三表联合查询
SELECT 学生信息.姓名 AS 姓名, 学生课程.名称 AS 课程, 学生成绩.成绩 AS 成绩
FROM 学生信息
LEFT OUTER JOIN 学生成绩 ON 学生信息.学号 = 学生成绩.学号
LEFT OUTER JOIN 学生课程 ON 学生成绩.课程编号 = 学生课程.编号
WHERE 成绩 > 60
ORDER BY 成绩 DESC;
四、C语言数据库编程(SQLite API)
SQLite提供了一套C语言接口,允许程序直接操作数据库。核心API如下:
4.1 打开数据库:sqlite3_open
int sqlite3_open(const char *filename, sqlite3 **ppDb);
-
功能:打开(或创建)一个SQLite数据库文件,返回数据库句柄
sqlite3 *。 -
返回值:成功返回
SQLITE_OK,否则返回错误码。
4.2 错误处理:sqlite3_errmsg
const char *sqlite3_errmsg(sqlite3 *db);
- 功能:根据数据库句柄获取最后一次操作的错误描述。
4.3 执行SQL语句:sqlite3_exec
int sqlite3_exec(
sqlite3 *db, /* 数据库句柄 */
const char *sql, /* 要执行的SQL语句 */
int (*callback)(void*, int, char**, char**), /* 回调函数(处理查询结果) */
void *arg, /* 传递给回调函数的参数 */
char **errmsg /* 错误信息指针 */
);
-
该函数可以执行任何SQL语句(DDL、DML、DQL)。
-
对于SELECT语句,每检索到一行就会调用一次回调函数。回调函数原型:
int callback(void *arg, int nColumns, char **colValues, char **colNames);-
arg:用户传入的参数。 -
nColumns:当前行的列数。 -
colValues:字符串数组,存放各列的值。 -
colNames:字符串数组,存放各列的字段名。 -
返回值:0表示继续处理后续行,非0则终止查询。
-
4.4 释放错误信息:sqlite3_free
void sqlite3_free(void *ptr);
- 用于释放
sqlite3_exec中由errmsg分配的内存。
4.5 关闭数据库:sqlite3_close
int sqlite3_close(sqlite3 *db);
- 关闭数据库连接,释放资源。
4.6 示例:查询学生信息
#include <stdio.h>
#include <sqlite3.h>
int callback(void *arg, int nCol, char **val, char **colName) {
for (int i = 0; i < nCol; i++)
printf("%s = %s\n", colName[i], val[i] ? val[i] : "NULL");
printf("\n");
return 0;
}
int main() {
sqlite3 *db;
char *errmsg = NULL;
int rc = sqlite3_open("test.db", &db);
if (rc != SQLITE_OK) {
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
return 1;
}
const char *sql = "SELECT * FROM student;";
rc = sqlite3_exec(db, sql, callback, NULL, &errmsg);
if (rc != SQLITE_OK) {
fprintf(stderr, "SQL error: %s\n", errmsg);
sqlite3_free(errmsg);
}
sqlite3_close(db);
return 0;
}
编译时需要链接SQLite库:
gcc example.c -lsqlite3 -o example
五、实践作业分析
本次学习的作业之一是构建一个单词查询系统,要求:
-
将单词文件中的所有单词和含义插入到数据库中。
-
从终端输入单词,通过数据库查找对应的含义并打印;若无匹配则提示输入有误。



