SQL约束是数据库设计的核心机制,用于强制数据完整性和业务规则。以下按约束类型分类解析,包含基础语法、参数说明、应用场景和实战示例,仅供参考。
一、SQL约束的基础概念
作用:在数据插入/更新时自动校验,防止非法数据破坏完整性
分类:
- 列级约束:直接定义在字段后(CREATE TABLE时)
- 表级约束:独立声明在所有字段后(支持多字段组合约束)
 共性特征:
- 违反约束时操作被终止,抛出错误代码(如MySQL 1062主键冲突)
- 支持CREATE TABLE或ALTER TABLE两种定义方式
数据完整性类型:
二、SQL约束类型详解
1. NOT NULL 约束
作用:禁止字段存储NULL值(空值 ≠ 0或空字符串)
语法:
-- 创建表时定义
CREATE TABLE 表名 (
    字段名 数据类型 NOT NULL
);
-- 修改表结构
ALTER TABLE 表名 
MODIFY 字段名 数据类型 NOT NULL;  -- MySQL/PostgreSQL
ALTER TABLE 表名 
ALTER COLUMN 字段名 SET NOT NULL; -- SQL Server
重要特性:
实战示例:
-- 创建用户表
CREATE TABLE Users (
    UserID INT PRIMARY KEY,
    UserName VARCHAR(50) NOT NULL,  -- 用户名不能为空
    BirthDate DATE NOT NULL         -- 出生日期必填
);
-- 插入非法数据(触发约束)
INSERT INTO Users (UserID, UserName) 
VALUES (1, 'Alice'); 
-- 错误: Column 'BirthDate' cannot be null
2. UNIQUE 约束
作用:确保字段值全表唯一(允许多个NULL)
语法:
-- 单字段列级约束
CREATE TABLE 表名 (
    字段名 数据类型 UNIQUE
);
-- 多字段表级约束
CREATE TABLE 表名 (
    字段1 数据类型,
    字段2 数据类型,
    CONSTRAINT 约束名 UNIQUE (字段1, 字段2)
);
-- 修改表添加约束
ALTER TABLE 表名 
ADD CONSTRAINT 约束名 UNIQUE (字段);
跨数据库差异:
实战示例:
-- 创建员工邮箱表
CREATE TABLE Employees (
    EmpID INT PRIMARY KEY,
    Email VARCHAR(100) UNIQUE,  -- 邮箱唯一
    Phone VARCHAR(20)
);
-- 添加复合唯一约束(部门+工号)
ALTER TABLE Employees 
ADD CONSTRAINT uniq_dept_emp 
UNIQUE (DeptID, EmpCode);
-- 插入冲突数据
INSERT INTO Employees (EmpID, Email) 
VALUES (1, 'alice@company.com');
INSERT INTO Employees (EmpID, Email) 
VALUES (2, 'alice@company.com'); 
-- 错误: Duplicate entry 'alice@company.com'
3. PRIMARY KEY 约束
作用:唯一标识行数据(NOT NULL + UNIQUE)
语法:
-- 单字段主键
CREATE TABLE 表名 (
    字段名 数据类型 PRIMARY KEY  -- 列级
);
-- 多字段主键(表级)
CREATE TABLE 表名 (
    字段1 数据类型,
    字段2 数据类型,
    CONSTRAINT pk_name PRIMARY KEY (字段1, 字段2)
);
-- 添加主键
ALTER TABLE 表名 
ADD PRIMARY KEY (字段);  -- 匿名约束
ALTER TABLE 表名 
ADD CONSTRAINT pk_name PRIMARY KEY (字段);
核心规则:
实战示例:
-- 创建订单表
CREATE TABLE Orders (
    OrderID INT PRIMARY KEY,     -- 列级主键
    OrderDate DATE NOT NULL
);
-- 创建订单详情(复合主键)
CREATE TABLE OrderDetails (
    OrderID INT,
    ProductID INT,
    Quantity INT,
    CONSTRAINT pk_order_product 
    PRIMARY KEY (OrderID, ProductID)  -- 表级
);
-- 非法数据插入
INSERT INTO Orders (OrderID, OrderDate) 
VALUES (1, '2023-01-01');
INSERT INTO Orders (OrderID, OrderDate) 
VALUES (1, '2023-02-01'); 
-- 错误: Duplicate entry '1'for key 'PRIMARY'
4. FOREIGN KEY 约束
作用:强制表间引用完整性(子表引用父表主键)
语法:
-- 创建表时定义
CREATE TABLE 子表 (
    子表字段 数据类型,
    CONSTRAINT fk_name 
    FOREIGN KEY (子表字段) 
    REFERENCES 父表(父表字段)
    [ON DELETE 动作]  -- 级联操作
    [ON UPDATE 动作]
);
-- 添加外键
ALTER TABLE 子表 
ADD CONSTRAINT fk_name 
FOREIGN KEY (子表字段) 
REFERENCES 父表(父表字段);
级联操作(可选):
|  |  | 
|---|
| NO ACTION |  | 
| CASCADE |  | 
| SET NULL |  | 
| SET DEFAULT |  | 
实战示例:
-- 父表:部门
CREATE TABLE Departments (
    DeptID INT PRIMARY KEY,
    DeptName VARCHAR(50)
);
-- 子表:员工(带级联删除)
CREATE TABLE Employees (
    EmpID INT PRIMARY KEY,
    DeptID INT,
    CONSTRAINT fk_emp_dept 
    FOREIGN KEY (DeptID) 
    REFERENCES Departments(DeptID)
    ON DELETE CASCADE  -- 部门删除时员工自动删除
);
-- 插入关联数据
INSERT INTO Departments VALUES (1, 'IT');
INSERT INTO Employees VALUES (101, 1);
-- 测试级联删除
DELETE FROM Departments WHERE DeptID = 1;
-- 结果:Employees中EmpID=101的记录自动删除
5. CHECK 约束
作用:定义字段值的业务规则(类似WHERE条件)
语法:
-- 列级约束
CREATE TABLE 表名 (
    字段名 数据类型 CHECK (条件)
);
-- 表级多字段约束
CREATE TABLE 表名 (
    字段1 数据类型,
    字段2 数据类型,
    CONSTRAINT chk_name CHECK (字段1 > 字段2)
);
-- 添加约束
ALTER TABLE 表名 
ADD CONSTRAINT chk_name CHECK (条件);
特殊规则:
实战示例:
-- 创建账户表
CREATE TABLE Accounts (
    AccountID INT PRIMARY KEY,
    Balance DECIMAL(10,2) CHECK (Balance >= 0),  -- 余额不可负
    Status VARCHAR(10) CHECK (Status IN ('ACTIVE', 'CLOSED'))
);
-- 添加自定义规则(开户日期早于今日)
ALTER TABLE Accounts 
ADD CONSTRAINT chk_open_date 
CHECK (OpenDate < GETDATE());
-- 违反约束测试
INSERT INTO Accounts 
VALUES (1, -100.00, 'ACTIVE'); 
-- 错误: Check constraint 'Balance>=0' violated
6. DEFAULT 约束
作用:字段未赋值时自动填充默认值
语法:
-- 创建表时定义
CREATE TABLE 表名 (
    字段名 数据类型 DEFAULT 默认值
);
-- 修改默认值
ALTER TABLE 表名 
ALTER COLUMN 字段名 SET DEFAULT 值;  -- MySQL/PostgreSQL
ALTER TABLE 表名 
ADD CONSTRAINT 约束名 DEFAULT 值 FOR 字段;  -- SQL Server
常用默认值:
- 系统函数:DEFAULT GETDATE()(当前时间)
- 表达式:DEFAULT (UUID())(生成唯一ID)
实战示例:
-- 创建用户注册表
CREATE TABLE Registrations (
    UserID INT PRIMARY KEY,
    RegDate DATE DEFAULT GETDATE(),  -- 自动填充注册日期
    Status VARCHAR(10) DEFAULT 'PENDING'
);
-- 插入数据(忽略默认字段)
INSERT INTO Registrations (UserID) VALUES (1001);
-- 查询结果
SELECT * FROM Registrations;
/*
UserID | RegDate     | Status
1001   | 2023-10-05  | PENDING
*/
7. INDEX(索引)
严格说索引非约束,但用于加速唯一性校验
作用:快速定位数据(UNIQUE/PRIMARY KEY自动创建)
语法:
CREATE INDEX 索引名 ON 表名 (字段);
CREATE UNIQUE INDEX 索引名 ON 表名 (字段); -- 唯一索引
与约束关系:
三、SQL约束管理技巧
1. 查看约束
-- SQL Server
SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS;
-- MySQL
SHOW CREATE TABLE 表名;
2. 删除约束
ALTER TABLE 表名 DROP CONSTRAINT 约束名;  -- 通用
ALTER TABLE 表名 DROP PRIMARY KEY;       -- 主键
ALTER TABLE 表名 DROP INDEX 索引名;       -- 索引
3. 临时禁用约束
-- MySQL外键开关
SET FOREIGN_KEY_CHECKS = 0;  -- 关闭
SET FOREIGN_KEY_CHECKS = 1;  -- 开启
-- SQL Server
ALTER TABLE 表名 NOCHECK CONSTRAINT ALL;
4. 约束设计建议
- 主键用无意义数字(自增ID/UUID),避免业务字段
- 慎用ON DELETE CASCADE(避免误删连锁反应)
综合实战:学生管理系统
-- 学院表(父表)
CREATE TABLE Colleges (
    CollegeID INT PRIMARY KEY,
    Name VARCHAR(50) NOT NULL UNIQUE
);
-- 学生表(子表)
CREATE TABLE Students (
    StudentID INT PRIMARY KEY,
    Name VARCHAR(50) NOT NULL,
    IDCard CHAR(18) UNIQUE,  -- 身份证唯一
    CollegeID INT NOT NULL,
    EnrollmentDate DATE DEFAULT GETDATE(),
    GPA DECIMAL(3,2) CHECK (GPA BETWEEN 0 AND 4.0),
    
    -- 表级外键(级联更新)
    CONSTRAINT fk_student_college 
    FOREIGN KEY (CollegeID) 
    REFERENCES Colleges(CollegeID)
    ON UPDATE CASCADE
);
-- 课程表
CREATE TABLE Courses (
    CourseID INT PRIMARY KEY,
    Credit INT CHECK (Credit > 0)  -- 学分需正数
);
-- 插入测试数据
INSERT INTO Colleges VALUES (1, '计算机学院');
INSERT INTO Students (StudentID, Name, CollegeID) 
VALUES (1001, '张三', 1);  -- 自动填充注册日期
-- 错误测试:无效学院
INSERT INTO Students VALUES (1002, '李四', '310101...', 99, '2023-09-01', 3.8);
-- 报错: Foreign key constraint violation
系统约束清单:
总结
SQL约束是数据库的“守门员”,通过七类机制保障数据质量:
我们要合理使用SQL约束减少应用层校验代码,从根本上杜绝脏数据。
阅读原文:原文链接
该文章在 2025/9/1 12:06:37 编辑过