Go语言从零开始构建SQL数据库(1)

关系型数据库基本概念

想象一下,你正在经营一家小型咖啡店。每天,你需要记录订单、管理库存、跟踪常客的喜好。起初,你用纸笔记录一切,但随着业务增长,这变得越来越复杂。

这就是数据库的用武之处!

数据管理的演进

最初,数据管理很简单:

复制代码
纸质账本 → 电子表格 → 专用软件 → 数据库系统

随着数据量增长,简单方法逐渐不够用:

  • 纸质账本难以查找和统计
  • 电子表格难以处理复杂关系
  • 专用软件缺乏灵活性

关系模型的诞生

1970年,IBM研究员E.F.Codd提出了关系模型的概念。在此之前,数据存储主要是层次模型和网络模型。

层次模型

在层次模型中,数据组织如下:

markdown 复制代码
咖啡店
 ├── 员工
 │    ├── 张三
 │    └── 李四
 └── 商品
      ├── 咖啡
      └── 点心

数据以树状结构组织,每个记录只能有一个父节点。要查找"李四销售的所有咖啡",必须遵循固定路径:咖啡店→员工→李四→销售记录→咖啡,非常不灵活。

网络模型

网络模型是层次模型的扩展,允许记录有多个父节点,形成网状结构:

markdown 复制代码
       ┌───────┐
       │ 咖啡店 │
       └───┬───┘
           │
    ┌──────┴──────┐
    ▼              ▼
┌───────┐      ┌───────┐
│  员工  │◄────►│  商品  │
└───┬───┘      └───┬───┘
    │              │
┌───┴───┐      ┌───┴───┐
│  张三  │◄────►│  咖啡  │
└───────┘      └───────┘
    ▲              ▲
    └──────┬───────┘
           │
       ┌───┴───┐
       │  销售  │
       └───────┘

网络模型通过"集合"连接不同记录,允许更复杂的关系。例如,员工可以销售商品,商品可以被多个员工销售。但数据访问仍需按特定路径导航,编程复杂且不直观。

关系模型

关系模型将数据组织为独立表格,通过共同值关联:

复制代码
【员工表】             【商品表】             【销售表】
┌────┬─────────┐      ┌────┬─────────┐      ┌────┬────────┬────────┐
│ ID │ 姓名    │      │ ID │ 名称    │      │ ID │ 员工ID │ 商品ID │
├────┼─────────┤      ├────┼─────────┤      ├────┼────────┼────────┤
│ 1  │ 张三    │      │ 1  │ 咖啡    │      │ 1  │ 1      │ 1      │
│ 2  │ 李四    │      │ 2  │ 点心    │      │ 2  │ 2      │ 1      │
└────┴─────────┘      └────┴─────────┘      └────┴────────┴────────┘

查询"李四销售的所有咖啡"只需一个简单的SQL语句,无需按特定路径导航:

sql 复制代码
SELECT 商品.名称
FROM 员工, 销售, 商品
WHERE 员工.姓名 = '李四' 
  AND 员工.ID = 销售.员工ID
  AND 销售.商品ID = 商品.ID;

核心概念:表与关系

表是关系型数据库的基本存储单元。以咖啡店为例:

复制代码
【商品表】
┌────┬───────────┬──────┬────────┬────────┐
│ ID │ 名称      │ 类别  │ 价格   │ 库存   │
├────┼───────────┼──────┼────────┼────────┤
│ 1  │ 美式咖啡   │ 饮品  │ 25.00  │ 无限   │
│ 2  │ 拿铁      │ 饮品  │ 32.00  │ 无限   │
│ 3  │ 牛角面包  │ 食品  │ 15.00  │ 20     │
└────┴───────────┴──────┴────────┴────────┘

每张表由以下元素组成:

  • 表名:描述表示什么实体(如"商品表")
  • :描述实体的属性(如ID、名称、价格)
  • :表示实体的具体实例(如"美式咖啡")
  • 单元格:包含特定实例的特定属性值(如"美式咖啡"的价格是25元)

数据关系:通过键连接

在关系模型中,表通过键连接。例如,我们可以有三张表:顾客、商品和订单,它们通过主键和外键相关联。

键的类型

  • 主键(PK):唯一标识表中的行,如商品表的ID列
  • 外键(FK):引用其他表主键的列,如订单表中的顾客ID
  • 候选键:能唯一标识行的任何列组合
  • 超键:包含候选键的任何列组合

把键想象成连接表的"桥梁":顾客表中的ID=1(张三)关联到订单表中顾客ID=1的所有记录。

数据完整性:通过约束保证

约束确保数据库中的数据符合业务规则:

  • 非空约束:值不能为NULL
  • 唯一约束:值不能重复
  • 检查约束:值必须满足条件
  • 引用完整性:外键必须引用有效值

例如,我们可以定义:

sql 复制代码
-- 价格必须为正数
ALTER TABLE 商品表 ADD CONSTRAINT 价格检查 CHECK (价格 > 0);

-- 订单中的商品ID必须存在于商品表
ALTER TABLE 订单表 ADD CONSTRAINT 商品存在
FOREIGN KEY (商品ID) REFERENCES 商品表(ID);

基本操作:CRUD

所有数据库操作都可以归结为四种基本类型:

  • Create (创建)
  • Read (读取)
  • Update (更新)
  • Delete (删除)

以咖啡店为例:

sql 复制代码
-- 创建:咖啡店新增一款饮品
INSERT INTO 商品表(ID, 名称, 类别, 价格, 库存)
VALUES (4, '摩卡', '饮品', 30.00, '无限');

-- 读取:查看所有饮品
SELECT * FROM 商品表 WHERE 类别 = '饮品';

-- 更新:调整拿铁价格
UPDATE 商品表 SET 价格 = 35.00 WHERE ID = 2;

-- 删除:下架牛角面包
DELETE FROM 商品表 WHERE ID = 3;

SQL与关系代数

SQL语句直接对应关系代数操作:

  • WHERE 子句 对应 选择(σ) 操作
  • SELECT 子句 对应 投影(π) 操作
  • JOIN 操作 对应 连接(⋈) 操作
  • UNION/INTERSECT/EXCEPT 对应 集合运算

例如:

  • SELECT 名称, 价格 FROM 商品表 WHERE 类别 = '饮品'
  • 相当于关系代数:π(名称,价格)(σ(类别='饮品')(商品表))

但是这并不是本教程的重点,所以咱们只要简单了解一下即可。

数据库系统架构

随着我们的学习深入,我们将逐层构建数据库系统:

markdown 复制代码
客户端接口层
    ↓
查询处理层
    ↓
事务管理层
    ↓
缓冲管理层
    ↓
存储引擎层
    ↓
文件系统

这种分层架构让我们能够逐步构建数据库系统,先实现基础功能,再添加高级特性。这里简单说说,后面这块我们将进行详细阐述。

小结与展望

在这一节中,我们了解了关系型数据库的核心概念:

  • 表和关系的基本结构
  • 键的类型和作用
  • 约束的重要性
  • 基本CRUD操作
  • 关系代数与SQL的对应关系

在下一节中,我们将探索SQL标准及其在不同数据库系统中的实现差异,为我们自己的数据库引擎奠定更坚实的理论基础。

我们的学习路径将是循序渐进的,从简单概念开始,逐步构建完整的数据库系统。不久后,我们就会开始编写代码,实现这些概念!

相关推荐
一个public的class3 分钟前
什么是 Java 泛型
java·开发语言·后端
头孢头孢1 小时前
k8s常用总结
运维·后端·k8s
TheITSea1 小时前
后端开发 SpringBoot 工程模板
spring boot·后端
Asthenia04121 小时前
编译原理中的词法分析器:从文本到符号的桥梁
后端
Asthenia04122 小时前
用RocketMQ和MyBatis实现下单-减库存-扣钱的事务一致性
后端
Pasregret2 小时前
04-深入解析 Spring 事务管理原理及源码
java·数据库·后端·spring·oracle
Micro麦可乐2 小时前
最新Spring Security实战教程(七)方法级安全控制@PreAuthorize注解的灵活运用
java·spring boot·后端·spring·intellij-idea·spring security
returnShitBoy2 小时前
Go语言中的defer关键字有什么作用?
开发语言·后端·golang
Asthenia04122 小时前
面试场景题:基于Redisson、RocketMQ和MyBatis的定时短信发送实现
后端
Asthenia04123 小时前
链路追踪视角:MyBatis-Plus 如何基于 MyBatis 封装 BaseMapper
后端