SQlite:列级,表级约束
目录
先明确:什么是“列级”和“表级”?
场景1:列级约束——管好单个字段的规则
场景2:表级约束——管好多个列的组合规则
最典型的表级约束:复合主键
总结:什么时候用列级/表级?
用“电商订单系统”的场景来理解“列级约束”和“表级约束”的区别,你会发现它们本质是“约束作用范围”的不同——有的约束只管单个列,有的约束需要管多个列。
先明确:什么是“列级”和“表级”?
简单说:
-
列级约束:绑在某一个列上,只对这一列生效(比如“手机号不能为空”);
-
表级约束:不绑在单个列上,对表中多个列的组合生效(比如“同一用户不能在同一时间下两单”)。
场景1:列级约束——管好单个字段的规则
假设你要设计一张user(用户表),需要保证:
-
用户ID(
user_id)唯一且非空(主键); -
手机号(
phone)不能为空,且不能重复(避免一个手机号注册多个账号); -
年龄(
age)必须大于0(不能是负数或0)。
这些规则都只针对单个列,适合用列级约束(在列定义时直接加规则):
CREATE TABLE user (user_id INTEGER PRIMARY KEY, -- 列级:主键(唯一+非空)phone TEXT NOT NULL UNIQUE, -- 列级:非空+唯一(单个列的规则)age INTEGER CHECK(age > 0), -- 列级:年龄必须>0(单个列的范围)name TEXT
);
-
特点:每个约束都跟在具体列后面,只限制这一列的数据(比如
phone的NOT NULL不会影响name列)。 -
注意:
NOT NULL只能用列级约束(因为它本质就是限制“某一列不能空”,不可能涉及多列)。
场景2:表级约束——管好多个列的组合规则
再设计一张order(订单表),需要保证:
-
订单由“用户ID(
user_id)+ 下单时间(order_time)”共同标识(同一用户同一时间不能下两单); -
订单的“支付金额(
pay_amount)”必须大于“商品金额(goods_amount)”(避免支付金额小于商品金额的错误)。
这些规则涉及多个列,必须用表级约束(在所有列定义完后,单独写规则):
CREATE TABLE "order" (order_id INTEGER,user_id INTEGER,order_time TEXT,goods_amount REAL, -- 商品金额pay_amount REAL, -- 支付金额-- 表级约束:多个列的组合规则PRIMARY KEY (order_id), -- 单列主键也可以放表级(但习惯放列级)UNIQUE (user_id, order_time), -- 表级:user_id+order_time组合唯一CHECK (pay_amount >= goods_amount) -- 表级:两列数值比较
);
-
为什么用表级?
-
UNIQUE (user_id, order_time):限制的是“两列组合”不能重复(单个user_id或order_time可以重复),列级约束做不到(列级只能限制单个列唯一); -
CHECK (pay_amount >= goods_amount):需要比较两个列的值,列级约束只能检查当前列(比如pay_amount单独CHECK(pay_amount>0)),不能跨列比较。
-
最典型的表级约束:复合主键
比如“用户-课程选课表”(student_course),需要“学生ID+课程ID”组合唯一(一个学生不能重复选同一门课)。这是必须用表级约束的场景:
CREATE TABLE student_course (student_id INTEGER,course_id INTEGER,score INTEGER,-- 表级:复合主键(只能表级定义)PRIMARY KEY (student_id, course_id)
);
-
为什么不能用列级?
列级主键只能绑一个列(比如
student_id INTEGER PRIMARY KEY),但这里需要两个列组合起来当主键,所以必须在表级定义。
总结:什么时候用列级/表级?
| 约束类型 | 列级约束(单个列) | 表级约束(多个列) |
|---|---|---|
| 适用场景 | 只限制某一列的规则(如非空、单列唯一、单列范围) | 限制多列组合的规则(如复合主键、多列唯一、跨列比较) |
| 典型例子 |
|
|
| 特殊点 |
| 复合约束(多列)必须用表级 |
面试时记住核心区别:列级管单个列,表级管多列组合。遇到“复合主键”“多列唯一”“跨列检查”的场景,直接说用表级约束,这就是得分点~
