SQL约束入门教程
全面学习SQL约束:确保数据完整性和一致性的关键工具
目录
SQL约束简介
SQL约束是应用于表中列的规则,用于限制可以存储在表中的数据类型。约束有助于确保数据库中数据的准确性和可靠性。
为什么需要约束?
- 数据完整性:确保数据的准确性和一致性
- 业务规则:强制执行特定的业务逻辑
- 数据质量:防止无效数据的输入
- 关系维护:保持表之间的正确关系
PRIMARY KEY
唯一标识每条记录
FOREIGN KEY
维护表间关系
NOT NULL
确保列不能为空
UNIQUE
确保所有值都不同
CHECK
确保列值满足条件
DEFAULT
为列提供默认值
注意: 约束可以在创建表时定义,也可以在创建表后使用ALTER TABLE语句添加。
PRIMARY KEY 主键约束
主键约束
唯一标识表中的每条记录
特点:
- 主键必须包含唯一值
- 主键列不能包含NULL值
- 每个表只能有一个主键
- 主键可以由单个列或多个列(复合主键)组成
语法示例
-- 创建表时定义主键
CREATE TABLE Students (
student_id INT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(100)
);
-- 使用复合主键
CREATE TABLE OrderDetails (
order_id INT,
product_id INT,
quantity INT,
PRIMARY KEY (order_id, product_id)
);
-- 为现有表添加主键
ALTER TABLE Students
ADD PRIMARY KEY (student_id);
CREATE TABLE Students (
student_id INT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(100)
);
-- 使用复合主键
CREATE TABLE OrderDetails (
order_id INT,
product_id INT,
quantity INT,
PRIMARY KEY (order_id, product_id)
);
-- 为现有表添加主键
ALTER TABLE Students
ADD PRIMARY KEY (student_id);
主键约束示例
Students 表
student_id (PK)
name
email
最佳实践: 通常使用无意义的自增数字作为主键,而不是业务数据。
FOREIGN KEY 外键约束
外键约束
用于链接两个表,保持引用完整性
特点:
- 外键是一个表中的字段,它是另一个表的主键
- 防止破坏表之间关系的操作
- 确保数据只能插入存在于被引用表中的值
语法示例
-- 创建外键约束
CREATE TABLE Orders (
order_id INT PRIMARY KEY,
customer_id INT,
order_date DATE,
FOREIGN KEY (customer_id) REFERENCES Customers(customer_id)
);
-- 带有级联操作的外键
CREATE TABLE OrderDetails (
order_id INT,
product_id INT,
FOREIGN KEY (order_id) REFERENCES Orders(order_id)
ON DELETE CASCADE
ON UPDATE CASCADE
);
CREATE TABLE Orders (
order_id INT PRIMARY KEY,
customer_id INT,
order_date DATE,
FOREIGN KEY (customer_id) REFERENCES Customers(customer_id)
);
-- 带有级联操作的外键
CREATE TABLE OrderDetails (
order_id INT,
product_id INT,
FOREIGN KEY (order_id) REFERENCES Orders(order_id)
ON DELETE CASCADE
ON UPDATE CASCADE
);
外键关系示例
Customers 表
customer_id (PK)
name
Orders 表
order_id (PK)
customer_id (FK)
order_date
外键操作
| 操作 | 描述 |
|---|---|
| NO ACTION | 如果存在相关记录,阻止删除或更新操作 |
| CASCADE | 删除或更新父表记录时,自动删除或更新子表相关记录 |
| SET NULL | 删除或更新父表记录时,将子表相关记录设为NULL |
| SET DEFAULT | 删除或更新父表记录时,将子表相关记录设为默认值 |
NOT NULL 非空约束
非空约束
确保列不能存储NULL值
特点:
- 强制字段必须包含值
- 在插入或更新数据时,该列必须有值
- 常用于必填字段,如用户名、密码等
语法示例
-- 创建表时定义NOT NULL约束
CREATE TABLE Users (
user_id INT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL,
phone VARCHAR(20) -- 可以为NULL
);
-- 为现有表添加NOT NULL约束
ALTER TABLE Users
MODIFY phone VARCHAR(20) NOT NULL;
CREATE TABLE Users (
user_id INT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL,
phone VARCHAR(20) -- 可以为NULL
);
-- 为现有表添加NOT NULL约束
ALTER TABLE Users
MODIFY phone VARCHAR(20) NOT NULL;
| user_id | username | phone | |
|---|---|---|---|
| 1 | john_doe | john@example.com | 123-456-7890 |
| 2 | jane_smith | jane@example.com | NULL |
注意: 主键自动具有NOT NULL约束,不需要显式指定。
UNIQUE 唯一约束
唯一约束
确保列中的所有值都是不同的
特点:
- 保证列中每个值都是唯一的
- 与主键不同,唯一约束允许NULL值
- 一个表可以有多个唯一约束
- 可以应用于单个列或多个列的组合
语法示例
-- 创建表时定义唯一约束
CREATE TABLE Employees (
emp_id INT PRIMARY KEY,
email VARCHAR(100) UNIQUE,
phone VARCHAR(20) UNIQUE
);
-- 复合唯一约束
CREATE TABLE Enrollments (
student_id INT,
course_id INT,
semester VARCHAR(10),
UNIQUE (student_id, course_id, semester)
);
-- 为现有表添加唯一约束
ALTER TABLE Employees
ADD CONSTRAINT uc_email UNIQUE (email);
CREATE TABLE Employees (
emp_id INT PRIMARY KEY,
email VARCHAR(100) UNIQUE,
phone VARCHAR(20) UNIQUE
);
-- 复合唯一约束
CREATE TABLE Enrollments (
student_id INT,
course_id INT,
semester VARCHAR(10),
UNIQUE (student_id, course_id, semester)
);
-- 为现有表添加唯一约束
ALTER TABLE Employees
ADD CONSTRAINT uc_email UNIQUE (email);
重要: UNIQUE约束允许NULL值,但每个NULL值被认为是唯一的。多个NULL值不会违反约束。
CHECK 检查约束
检查约束
限制列中值的范围
特点:
- 确保列值满足特定条件
- 可以基于逻辑表达式定义约束
- 在插入或更新时验证数据
- 可以应用于单个列或整个表
语法示例
-- 创建表时定义CHECK约束
CREATE TABLE Products (
product_id INT PRIMARY KEY,
product_name VARCHAR(100),
price DECIMAL(10,2) CHECK (price > 0),
stock_quantity INT CHECK (stock_quantity >= 0)
);
-- 多列CHECK约束
CREATE TABLE Employees (
emp_id INT PRIMARY KEY,
salary DECIMAL(10,2),
bonus DECIMAL(10,2),
CHECK (bonus <= salary * 0.5)
);
-- 为现有表添加CHECK约束
ALTER TABLE Products
ADD CONSTRAINT chk_price CHECK (price > 0);
CREATE TABLE Products (
product_id INT PRIMARY KEY,
product_name VARCHAR(100),
price DECIMAL(10,2) CHECK (price > 0),
stock_quantity INT CHECK (stock_quantity >= 0)
);
-- 多列CHECK约束
CREATE TABLE Employees (
emp_id INT PRIMARY KEY,
salary DECIMAL(10,2),
bonus DECIMAL(10,2),
CHECK (bonus <= salary * 0.5)
);
-- 为现有表添加CHECK约束
ALTER TABLE Products
ADD CONSTRAINT chk_price CHECK (price > 0);
常见CHECK约束示例
-- 年龄范围检查
age INT CHECK (age >= 0 AND age <= 150)
-- 性别检查
gender VARCHAR(10) CHECK (gender IN ('男', '女', '其他'))
-- 邮箱格式检查(简单版本)
email VARCHAR(100) CHECK (email LIKE '%@%.%')
age INT CHECK (age >= 0 AND age <= 150)
-- 性别检查
gender VARCHAR(10) CHECK (gender IN ('男', '女', '其他'))
-- 邮箱格式检查(简单版本)
email VARCHAR(100) CHECK (email LIKE '%@%.%')
DEFAULT 默认约束
默认约束
为列提供默认值
特点:
- 在插入新记录时,如果未指定值,则使用默认值
- 可以设置固定值或系统函数
- 提高数据输入的效率
- 确保即使没有提供值,列也有合理的值
语法示例
-- 创建表时定义DEFAULT约束
CREATE TABLE Orders (
order_id INT PRIMARY KEY,
order_date DATE DEFAULT CURRENT_DATE,
status VARCHAR(20) DEFAULT 'pending',
total_amount DECIMAL(10,2) DEFAULT 0.00
);
-- 为现有表添加DEFAULT约束
ALTER TABLE Orders
ALTER COLUMN status SET DEFAULT 'pending';
CREATE TABLE Orders (
order_id INT PRIMARY KEY,
order_date DATE DEFAULT CURRENT_DATE,
status VARCHAR(20) DEFAULT 'pending',
total_amount DECIMAL(10,2) DEFAULT 0.00
);
-- 为现有表添加DEFAULT约束
ALTER TABLE Orders
ALTER COLUMN status SET DEFAULT 'pending';
常用默认值
| 默认值 | 描述 | 示例 |
|---|---|---|
| 固定值 | 预定义的常量值 | DEFAULT 'active' |
| 系统函数 | 数据库系统函数 | DEFAULT CURRENT_TIMESTAMP |
| 数学表达式 | 简单的计算表达式 | DEFAULT 0 |
注意: 如果插入时显式指定NULL值,将使用NULL而不是默认值。
综合示例
完整的表定义示例
CREATE TABLE Employees (
-- 主键约束
employee_id INT PRIMARY KEY,
-- 非空约束
first_name VARCHAR(50) NOT NULL,
last_name VARCHAR(50) NOT NULL,
-- 唯一约束
email VARCHAR(100) UNIQUE NOT NULL,
-- 检查约束
age INT CHECK (age >= 18 AND age <= 65),
salary DECIMAL(10,2) CHECK (salary > 0),
-- 默认约束
hire_date DATE DEFAULT CURRENT_DATE,
department_id INT DEFAULT 1,
-- 外键约束
FOREIGN KEY (department_id) REFERENCES Departments(department_id)
);
-- 主键约束
employee_id INT PRIMARY KEY,
-- 非空约束
first_name VARCHAR(50) NOT NULL,
last_name VARCHAR(50) NOT NULL,
-- 唯一约束
email VARCHAR(100) UNIQUE NOT NULL,
-- 检查约束
age INT CHECK (age >= 18 AND age <= 65),
salary DECIMAL(10,2) CHECK (salary > 0),
-- 默认约束
hire_date DATE DEFAULT CURRENT_DATE,
department_id INT DEFAULT 1,
-- 外键约束
FOREIGN KEY (department_id) REFERENCES Departments(department_id)
);
约束管理操作
-- 删除约束
ALTER TABLE Employees
DROP CONSTRAINT 约束名;
-- 禁用约束
ALTER TABLE Employees
NOCHECK CONSTRAINT 约束名;
-- 启用约束
ALTER TABLE Employees
CHECK CONSTRAINT 约束名;
ALTER TABLE Employees
DROP CONSTRAINT 约束名;
-- 禁用约束
ALTER TABLE Employees
NOCHECK CONSTRAINT 约束名;
-- 启用约束
ALTER TABLE Employees
CHECK CONSTRAINT 约束名;
约束总结表
| 约束类型 | 用途 | 是否允许多个 | 是否允许NULL |
|---|---|---|---|
| PRIMARY KEY | 唯一标识记录 | 否 | 否 |
| FOREIGN KEY | 维护表间关系 | 是 | 是 |
| NOT NULL | 防止NULL值 | 是 | 否 |
| UNIQUE | 确保值唯一 | 是 | 是 |
| CHECK | 验证数据范围 | 是 | 是 |
| DEFAULT | 提供默认值 | 是 | 是 |