在 SQL 中,約束(Constraint)是用于限制表中數據的規則,目的是保證數據的完整性、一致性和有效性。常見的約束類型包括:主鍵約束、外鍵約束、非空約束、唯一約束、檢查約束、默認值約束等。下面結合你提供的代碼,詳細講解這些約束及其應用。
一、SQL 中常見的約束類型
主鍵約束(PRIMARY KEY)
- 作用:唯一標識表中的每條記錄,確保記錄的唯一性。
- 特點:一個表只能有一個主鍵;主鍵列的值不能重復(唯一),且不能為
NULL
;通常與auto_increment
(自增)配合使用,自動生成唯一值。
非空約束(NOT NULL)
- 作用:限制列的值不能為
NULL
,必須提供具體數據。 - 特點:如果插入數據時未指定該列的值,會報錯。
- 作用:限制列的值不能為
唯一約束(UNIQUE)
- 作用:確保列中的所有值都是唯一的(不重復)。
- 特點:與主鍵的區別是,一個表可以有多個唯一約束;唯一約束允許列值為
NULL
(且可以有多個NULL
,因為NULL
不等于任何值)。
檢查約束(CHECK)
- 作用:限制列的值必須滿足指定的條件(如范圍、格式等)。
- 特點:確保數據符合業務規則,例如年齡必須在 0-120 之間。
默認值約束(DEFAULT)
- 作用:當插入數據時未指定該列的值,自動使用默認值。
外鍵約束(FOREIGN KEY)
- 作用:建立兩個表之間的關聯關系(父子表),確保子表中引用的外鍵值在主表的主鍵中存在(或為
NULL
),維護數據的參照完整性。 - 相關概念:
- 主表(父表):被引用的表(如
dept
表)。 - 子表(從表):引用主表的表(如
emp
表)。 - 外鍵列:子表中用于關聯主表主鍵的列(如
emp.dept_id
關聯dept.id
)。
- 主表(父表):被引用的表(如
- 級聯操作(通過
ON UPDATE
和ON DELETE
指定):CASCADE
:當主表的主鍵更新 / 刪除時,子表的外鍵值同步更新 / 刪除。SET NULL
:當主表的主鍵更新 / 刪除時,子表的外鍵值設為NULL
(需確保外鍵列允許NULL
)。
- 作用:建立兩個表之間的關聯關系(父子表),確保子表中引用的外鍵值在主表的主鍵中存在(或為
二、代碼詳解
以下是對提供的 SQL 代碼的逐段解釋:
1. 創建user
表
create table user(id int primary key auto_increment comment '主鍵', -- 主鍵約束+自增name varchar(10) not null unique comment '姓名', -- 非空約束+唯一約束age int check (age >= 0 and age <= 120) comment '年齡', -- 檢查約束status char(1) default '1' comment '狀態', -- 默認值約束gender char(1) comment '性別' -- 無特殊約束
)comment '用戶表';
id
:主鍵(primary key
),確保每條用戶記錄唯一;auto_increment
表示插入時無需手動指定,自動遞增生成。name
:not null
(必須提供姓名)+?unique
(姓名不能重復)。age
:check
約束限制年齡必須在 0-120 之間(若插入年齡為 150,會報錯)。status
:default '1'
表示若插入時未指定status
,默認值為 '1'(可理解為 “正常” 狀態)。
2. 插入數據到user
表
-- 插入3條完整數據
insert into user(name, age, status, gender) values
('Tom1', 19, '0', '男'),
('Tom2', 25, '1', '女'),
('Tom3', 17, '0', '男');-- 插入時未指定status,會使用默認值'1'
insert into user(name, age, gender) values ('Tom5', 32,'男');
- 第一條插入語句顯式指定了所有列的值,
status
分別為 '0'、'1'、'0'。 - 第二條插入語句未指定
status
,因此status
會自動使用默認值 '1'。
3. 創建dept
表(部門表)
create table dept(id int primary key auto_increment comment 'ID' , -- 主鍵+自增name varchar(50) not null comment '部門名稱' -- 非空約束
)comment '部門表';-- 插入部門數據
insert into dept values (1, '研發部'),(2,'市場部'),(3, '財務部'),(4, '銷售部'),(5, '總經辦');
id
:部門唯一標識(主鍵 + 自增)。name
:not null
確保部門名稱必須填寫(不能為NULL
)。
4. 創建emp
表(員工表)及外鍵操作
-- 創建員工表
create table emp(id int primary key auto_increment comment 'ID' , -- 主鍵+自增name varchar(50) not null comment '姓名', -- 非空約束age int comment '年齡',job varchar(20) comment '職位',salary int comment '薪資',entrydate date comment '入職時間',managerid int comment '直屬領導ID', -- 可關聯其他員工(自關聯)dept_id int comment '部門ID' -- 外鍵,關聯dept表的id
)comment '員工表';-- 插入員工數據
insert into emp values
(1, '金庸', 66, '總裁', 20000, '2000-01-01', null, 5), -- 總裁無領導(managerid為null),屬于總經辦(dept_id=5)
(2, '張無忌', 20, '項目經理', 12500, '2005-12-01', 1, 1), -- 領導是金庸(id=1),屬于研發部(dept_id=1)
... -- 其他員工數據
emp
表的dept_id
用于關聯dept
表的id
(表示員工所屬部門),后續通過外鍵約束正式建立關聯。
5. 外鍵約束的添加、刪除與修改
-- 第一次添加外鍵約束:關聯emp.dept_id到dept.id(無特殊級聯操作)
alter table emp add constraint fk_emp_dept_id
foreign key (dept_id) references dept(id);-- 刪除外鍵約束
alter table emp drop foreign key fk_emp_dept_id;-- 第二次添加外鍵:級聯更新和刪除(主表操作影響子表)
alter table emp add constraint fk_emp_dept_id
foreign key (dept_id) references dept(id)
on UPDATE cascade -- 當dept.id更新時,emp.dept_id同步更新
on DELETE cascade; -- 當dept的記錄刪除時,emp中對應記錄也刪除-- 第三次修改外鍵:主表操作時子表外鍵設為NULL
alter table emp add constraint fk_emp_dept_id
foreign key (dept_id) references dept(id)
on update set null -- 當dept.id更新時,emp.dept_id設為NULL
on delete set null; -- 當dept的記錄刪除時,emp.dept_id設為NULL
- 外鍵約束名稱
fk_emp_dept_id
是自定義的(通常格式為fk_子表_外鍵列
)。 - 第一次添加的外鍵無
ON UPDATE/DELETE
,表示若主表dept
的id
被更新或記錄被刪除,而子表emp
中仍有引用,會直接報錯(阻止操作)。 ON UPDATE CASCADE ON DELETE CASCADE
:例如,若dept
表中id=1
(研發部)被更新為10
,則emp
表中所有dept_id=1
的記錄會自動變為10
;若研發部記錄被刪除,所有屬于研發部的員工記錄也會被刪除。ON UPDATE SET NULL ON DELETE SET NULL
:例如,若研發部(id=1
)被刪除,emp
表中所有dept_id=1
的員工,其dept_id
會被設為NULL
(表示 “無部門”)。
三、總結
約束是 SQL 中保證數據質量的核心機制:
- 主鍵、唯一約束確保數據唯一性;
- 非空、檢查約束確保數據有效性;
- 默認值約束簡化數據插入;
- 外鍵約束維護表之間的關聯完整性,通過級聯操作靈活處理主表變更對從表的影響。