大概需要实现的效果:用单片机做一个闹钟。支持设置闹铃的时间和种类,到点时会在该种类里随机一首歌。可能需要联网,上传闹铃播放的时间存储在数据库里,也可能会联网找歌。

最近会有别的外出活动,因此先解决当中偏软件的部分。数据的量是小的,因此我们采用 Python + SQLite。

1. SQL 简介

SQL stands for Structured Query Language,基础目的是实现这样一种数据结构:

  • 定义结构:建立表格,每一列是什么类型,以及相应的约束,插入的数据不能违反约束,常见的约束有:
    • NOT NULL
    • UNIQUE
    • PRIMARY KEY:一张表只能有一个主键,用来唯一表示这一行数据,相当于 NOT NULL + UNIQUE
    • CHECK:只允许某些特定的键值
    • FOREIGN KEY:儿子表的某一列必须匹配父亲表的某一列。
  • 操作,至少支持以下操作:
    • INSERT
    • UPDATE
    • DELETE
  • 查询(SELECT),至少支持以下操作:
    • 全表扫描
    • 对于某个信息的单点查询,区间查询等
    • 部分支持模糊匹配的查询,比如特定前缀
  • 事务与持久化能力
    • 原子性 Atomicity:要么全做完,要么直接罢工
    • 一致性 Consistency:做之前是对的,做之后也是对的
    • 隔离性 Isolation:多个程序同时在写数据库时,互不干扰
    • 持久性 Durability:就算突然断电,数据也不会丢

其规则非常严格,不会接受脏数据,如果这个数据有问题会报错。

从查询可以看出其大概是通过平衡树实现的,因为其并不支持复杂的模糊匹配——比如搜索引擎,大概是通过把每个网页拆成关键词,然后某些关键词出现在了哪些网页里。确实有工具让 SQL 支持类似于这样的功能,但是以后再说。

我们采用 SQLite3 做一个简单的实验。假设现在有三个闹钟,分别叫做卧室、客厅和厨房,如果只用一张表然后某一列代表是哪个闹钟响的,如果某天客厅变书房了,那么完蛋了。

因此比较好的实现方式是父亲表 devices 存放设备清单,儿子表 alarm_logs 存放闹钟记录但是不存设备名字只存编号。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
-- 1. 创建父亲表(设备表)
CREATE TABLE devices (
id INTEGER PRIMARY KEY AUTOINCREMENT, -- AUTOINCREMENT 自增主键
device_name TEXT UNIQUE NOT NULL -- 设备名称,比如 'bedroom', 'living_room'
);

-- 2. 创建儿子表(日志表),关键点在于最后一句
CREATE TABLE alarm_logs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
alarm_time TEXT NOT NULL, -- 非空约束:必须有时间
category TEXT DEFAULT 'pop' CHECK (category IN ('pop', 'classic', 'rock')), -- 检查约束:只允许这三种
song_name TEXT,
device_ref INTEGER, -- 这一列用来存设备的ID
FOREIGN KEY (device_ref) REFERENCES devices (id) -- 约束:device_ref 必须在 devices 表里存在
);

这里我们先插入 devices

1
2
INSERT INTO devices (device_name) VALUES ('bedroom');
INSERT INTO devices (device_name) VALUES ('living_room');

这样插入日志表的时候,device_ref 就有限制,不能乱写:

1
INSERT INTO alarm_logs (alarm_time, category, song_name, device_ref) VALUES ('2026-07-06 07:00:00', 'pop', '0001.mp3', 1);

1.1 实现数据结构

主要写一下思路。

查找的效率是重要的,但是我们不可能对所有列都建一棵平衡树(通常只默认对 PRIMARY KEY 建),否则磁盘空间爆炸了,插入的时间复杂度也爆炸了。

而且不能采用二叉树,因为数据是存在磁盘上的。对于一次寻找儿子的操作,都意味着随机访问,这个是很慢(约 10ms,而内存是纳秒级的)

数据很多不可能存在内存里,但是该

2.


Nothing built can last forever.
本站由 iznomia 使用 Stellar 1.30.4 主题创建。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。