4. 表的创建与数据类型:CREATE TABLE语句、SQLite支持的数据类型、约束条件

好,咱们今天聊聊建表。这是数据库操作里最基础、也最核心的一步。你想想看,表就像是一个容器,你往里面放数据之前,总得先把这个容器设计好吧?我个人习惯是,在写第一行代码之前,先在脑子里把表的结构过一遍,甚至拿张纸画一画。别小看这一步,很多线上事故,追根溯源都是表结构设计埋下的坑。

4.1 CREATE TABLE 语句:搭起数据的骨架

在 SQLite 里,建表用的是 CREATE TABLE 语句。语法其实挺直观的,我直接给你看个例子:

CREATE TABLE 学生表 (
    学号    INTEGER PRIMARY KEY,
    姓名    TEXT    NOT NULL,
    年龄    INTEGER,
    成绩    REAL,
    备注    BLOB
);

嗯,这里要注意,SQLite 对 SQL 语句的大小写不敏感,但为了代码规范,我建议关键字全大写,表名和字段名用小写。这算是个好习惯,团队协作时能省不少事。

我在项目中遇到过一种情况:有人建表时忘了加字段类型,结果 SQLite 也能接受,默认存成 TEXT。但后续查询时,类型不一致导致排序结果完全乱套。所以,每个字段都要明确指定类型,别偷懒。

小提示:如果你不确定表是否存在,可以在建表前加一句 IF NOT EXISTS。比如:CREATE TABLE IF NOT EXISTS 学生表 (...)。这样即使表已经存在,也不会报错。

4.2 SQLite 支持的数据类型:就五种,但够用

SQLite 的数据类型跟 MySQL、PostgreSQL 不太一样。它只有五种存储类型,说白了就是:INTEGER、REAL、TEXT、BLOB、NULL。别觉得少,实际开发中完全够用。

类型 说明 我常用的场景
INTEGER 有符号整型,占 1~8 字节 主键、年龄、数量、状态码
REAL 浮点数,8 字节 IEEE 双精度 成绩、金额、经纬度
TEXT 字符串,支持 UTF-8、UTF-16 姓名、地址、描述、JSON 字符串
BLOB 二进制大对象,原样存储 图片、文件、加密数据
NULL 空值 表示数据缺失或未知

你可能会问:那日期时间怎么存?SQLite 没有专门的日期类型。我一般用 TEXT 存 ISO 8601 格式的字符串,比如 "2025-03-15 14:30:00"。这样排序、比较都很方便。当然,你也可以用 INTEGER 存 Unix 时间戳,看个人习惯。

这里有个坑我得提醒你:SQLite 是弱类型检查的。什么意思?就算你把字段声明成 INTEGER,你往里面塞一个 "hello" 字符串,它也不会报错。我曾经接手过一个项目,就是因为这种类型混乱,导致聚合函数 SUM 算出来的结果莫名其妙。所以,在应用层做好数据校验,别完全依赖数据库。

核心要点:SQLite 的 INTEGER 和 REAL 是数字类型,TEXT 是字符串,BLOB 是二进制。记住这四种就够了,NULL 不算真正的数据。

4.3 约束条件:给数据上规矩

光有类型还不够,你还得告诉数据库:哪些数据是必须的?哪些不能重复?哪些是唯一标识?这就是约束条件干的事。

4.3.1 PRIMARY KEY:每行数据的身份证

主键约束,说白了就是给每一行数据一个唯一的标识。一个表只能有一个主键,但主键可以由多个字段联合组成(这叫联合主键)。

-- 单字段主键
CREATE TABLE 学生表 (
    学号 INTEGER PRIMARY KEY,
    姓名 TEXT
);

-- 联合主键
CREATE TABLE 选课表 (
    学号 INTEGER,
    课程号 INTEGER,
    成绩 REAL,
    PRIMARY KEY (学号, 课程号)
);

我个人习惯用 INTEGER 类型做主键,并且让它自增。SQLite 里,如果你把主键声明为 INTEGER PRIMARY KEY,它就会自动变成自增的 ROWID 的别名。插入数据时你不给值,它会自动分配一个比当前最大值大 1 的整数。

注意:如果你用 TEXT 类型做主键,比如存 UUID 字符串,性能会比 INTEGER 主键差一些。因为 INTEGER 主键底层用的是 B-tree 的整数比较,比字符串比较快得多。

4.3.2 NOT NULL:拒绝空值

有些字段是必须有的,比如用户的手机号、订单的金额。这时候就用 NOT NULL 约束。

CREATE TABLE 用户表 (
    用户ID INTEGER PRIMARY KEY,
    手机号 TEXT NOT NULL,
    昵称 TEXT
);

我在项目中遇到过一个问题:有个字段本来应该存邮箱,但设计时没加 NOT NULL,结果线上数据有 30% 是空的。后续做邮件推送时,还得专门写脚本清洗数据。所以,业务上必须有的字段,一定要加 NOT NULL,别想着「以后再说」。

4.3.3 UNIQUE:保证数据不重复

有时候,某个字段的值不能重复,但它又不是主键。比如用户的身份证号、商品的条形码。这时候就用 UNIQUE 约束。

CREATE TABLE 商品表 (
    商品ID INTEGER PRIMARY KEY,
    条形码 TEXT UNIQUE,
    名称 TEXT NOT NULL,
    价格 REAL
);

你想想看,如果条形码可以重复,那扫码枪扫出来到底是哪个商品?所以 UNIQUE 约束在这里就派上用场了。

另外,UNIQUE 和 PRIMARY KEY 的区别在于:一个表可以有多个 UNIQUE 字段,但只能有一个 PRIMARY KEY。而且 UNIQUE 字段允许 NULL 值(但 NULL 值之间不算重复,所以可以有多行 NULL)。

小技巧:如果你需要多个字段联合唯一,可以这样写:UNIQUE (字段1, 字段2)。比如在选课表里,一个学生不能重复选同一门课,就可以用联合 UNIQUE 约束。

4.4 知识体系总览

说了这么多,我画了一张图帮你梳理一下本章的知识结构。这样你脑子里能有个整体框架。

表的创建与数据类型 - 知识体系 CREATE TABLE 数据类型 约束条件 最佳实践 INTEGER REAL TEXT BLOB NULL PRIMARY KEY NOT NULL UNIQUE 明确类型 应用层校验 INTEGER主键 核心:类型决定存储方式,约束保证数据质量

这张图把本章的核心内容串起来了。你写 CREATE TABLE 时,脑子里要同时想三件事:用什么类型存数据?加什么约束保证数据质量?有没有什么最佳实践可以避免踩坑?

好了,关于建表和数据类型,我就讲这么多。记住一句话:表结构设计得越严谨,后期维护越省心。别图一时方便,给未来埋雷。


公众号:蓝海资料掘金营,微信deep3321