茂名市本地咨询网

MySQL数据库的约束与设计解读

2026-03-29 09:12:02 浏览次数:1
详细信息

MySQL 数据库的约束与设计

一、数据库约束

1. 主键约束 (Primary Key)

-- 创建表时定义主键
CREATE TABLE users (
    id INT PRIMARY KEY,
    username VARCHAR(50) NOT NULL
);

-- 或使用约束语法
CREATE TABLE users (
    id INT,
    username VARCHAR(50),
    PRIMARY KEY (id)
);

-- 复合主键
CREATE TABLE order_items (
    order_id INT,
    product_id INT,
    quantity INT,
    PRIMARY KEY (order_id, product_id)
);

2. 外键约束 (Foreign Key)

CREATE TABLE orders (
    order_id INT PRIMARY KEY,
    user_id INT,
    order_date DATE,
    FOREIGN KEY (user_id) REFERENCES users(id)
    ON DELETE CASCADE  -- 级联删除
    ON UPDATE CASCADE  -- 级联更新
);

-- 其他引用操作
-- ON DELETE RESTRICT    -- 禁止删除(默认)
-- ON DELETE SET NULL   -- 设置为NULL
-- ON DELETE NO ACTION  -- 无操作

3. 唯一约束 (Unique)

CREATE TABLE employees (
    id INT PRIMARY KEY,
    email VARCHAR(100) UNIQUE,
    phone VARCHAR(20) UNIQUE
);

-- 复合唯一约束
CREATE TABLE user_roles (
    user_id INT,
    role_id INT,
    UNIQUE(user_id, role_id)
);

4. 非空约束 (NOT NULL)

CREATE TABLE products (
    id INT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    price DECIMAL(10,2) NOT NULL,
    description TEXT  -- 可为空
);

5. 检查约束 (CHECK)

-- MySQL 8.0+ 支持
CREATE TABLE students (
    id INT PRIMARY KEY,
    age INT CHECK (age >= 0 AND age <= 150),
    gender CHAR(1) CHECK (gender IN ('M', 'F')),
    score DECIMAL(5,2) CHECK (score >= 0 AND score <= 100)
);

6. 默认值约束 (DEFAULT)

CREATE TABLE articles (
    id INT PRIMARY KEY AUTO_INCREMENT,
    title VARCHAR(200) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    status ENUM('draft', 'published') DEFAULT 'draft',
    views INT DEFAULT 0
);

二、数据库设计原则

1. 范式化设计

第一范式 (1NF)
-- 不符合1NF
CREATE TABLE bad_design (
    id INT PRIMARY KEY,
    tags VARCHAR(200)  -- 存储多个标签:'java,mysql,database'
);

-- 符合1NF
CREATE TABLE posts (
    id INT PRIMARY KEY,
    title VARCHAR(200)
);

CREATE TABLE post_tags (
    post_id INT,
    tag VARCHAR(50),
    PRIMARY KEY (post_id, tag)
);
第二范式 (2NF) 第三范式 (3NF)

2. 反范式化设计

在某些情况下为了性能,可以有意识地违反范式:

-- 反范式设计:存储冗余数据提高查询性能
CREATE TABLE orders_with_total (
    order_id INT PRIMARY KEY,
    user_id INT,
    total_amount DECIMAL(10,2),  -- 冗余字段,可避免JOIN计算
    created_at TIMESTAMP
);

三、实体关系设计

1. 一对一关系

-- 用户基本信息表
CREATE TABLE users (
    user_id INT PRIMARY KEY,
    username VARCHAR(50),
    email VARCHAR(100)
);

-- 用户扩展信息表
CREATE TABLE user_profiles (
    user_id INT PRIMARY KEY,
    avatar_url VARCHAR(200),
    bio TEXT,
    FOREIGN KEY (user_id) REFERENCES users(user_id)
);

2. 一对多关系

-- 部门表
CREATE TABLE departments (
    dept_id INT PRIMARY KEY,
    dept_name VARCHAR(100)
);

-- 员工表
CREATE TABLE employees (
    emp_id INT PRIMARY KEY,
    emp_name VARCHAR(100),
    dept_id INT,
    FOREIGN KEY (dept_id) REFERENCES departments(dept_id)
);

3. 多对多关系

-- 学生表
CREATE TABLE students (
    student_id INT PRIMARY KEY,
    name VARCHAR(100)
);

-- 课程表
CREATE TABLE courses (
    course_id INT PRIMARY KEY,
    course_name VARCHAR(100)
);

-- 关联表
CREATE TABLE student_courses (
    student_id INT,
    course_id INT,
    enrollment_date DATE,
    grade DECIMAL(4,2),
    PRIMARY KEY (student_id, course_id),
    FOREIGN KEY (student_id) REFERENCES students(student_id),
    FOREIGN KEY (course_id) REFERENCES courses(course_id)
);

四、索引设计

1. 索引类型

-- 单列索引
CREATE INDEX idx_email ON users(email);

-- 复合索引
CREATE INDEX idx_name_dob ON users(last_name, first_name, date_of_birth);

-- 唯一索引
CREATE UNIQUE INDEX idx_unique_phone ON customers(phone);

-- 全文索引(适用于文本搜索)
CREATE FULLTEXT INDEX idx_content ON articles(content);

2. 索引设计原则

五、最佳实践示例

1. 完整的数据库设计示例

-- 用户表
CREATE TABLE users (
    user_id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) UNIQUE NOT NULL,
    email VARCHAR(100) UNIQUE NOT NULL,
    password_hash VARCHAR(255) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    is_active BOOLEAN DEFAULT TRUE,
    INDEX idx_email (email),
    INDEX idx_username (username)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- 博客文章表
CREATE TABLE articles (
    article_id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL,
    title VARCHAR(200) NOT NULL,
    slug VARCHAR(200) UNIQUE NOT NULL,
    content LONGTEXT,
    summary TEXT,
    status ENUM('draft', 'published', 'archived') DEFAULT 'draft',
    published_at TIMESTAMP NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    view_count INT DEFAULT 0,
    FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE,
    INDEX idx_user_status (user_id, status),
    INDEX idx_published (published_at),
    FULLTEXT INDEX idx_fulltext (title, content)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- 评论表
CREATE TABLE comments (
    comment_id INT AUTO_INCREMENT PRIMARY KEY,
    article_id INT NOT NULL,
    user_id INT NULL,
    parent_id INT NULL,
    content TEXT NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    is_approved BOOLEAN DEFAULT FALSE,
    FOREIGN KEY (article_id) REFERENCES articles(article_id) ON DELETE CASCADE,
    FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE SET NULL,
    FOREIGN KEY (parent_id) REFERENCES comments(comment_id) ON DELETE CASCADE,
    INDEX idx_article (article_id),
    INDEX idx_parent (parent_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

2. 数据完整性检查

-- 添加约束检查
ALTER TABLE products 
ADD CONSTRAINT chk_price 
CHECK (price >= 0 AND price <= 1000000);

-- 添加外键约束
ALTER TABLE orders 
ADD CONSTRAINT fk_user 
FOREIGN KEY (user_id) 
REFERENCES users(user_id);

-- 查看约束信息
SELECT 
    TABLE_NAME,
    CONSTRAINT_NAME,
    CONSTRAINT_TYPE
FROM information_schema.TABLE_CONSTRAINTS 
WHERE TABLE_SCHEMA = 'your_database';

六、性能优化设计

1. 分区表

-- 按范围分区
CREATE TABLE sales (
    sale_id INT AUTO_INCREMENT,
    sale_date DATE NOT NULL,
    amount DECIMAL(10,2),
    PRIMARY KEY (sale_id, sale_date)
) PARTITION BY RANGE (YEAR(sale_date)) (
    PARTITION p0 VALUES LESS THAN (2020),
    PARTITION p1 VALUES LESS THAN (2021),
    PARTITION p2 VALUES LESS THAN (2022),
    PARTITION p3 VALUES LESS THAN MAXVALUE
);

2. 垂直分表

-- 将大字段分离
CREATE TABLE user_basic (
    user_id INT PRIMARY KEY,
    username VARCHAR(50),
    email VARCHAR(100)
);

CREATE TABLE user_details (
    user_id INT PRIMARY KEY,
    bio TEXT,
    preferences JSON,
    metadata JSON,
    FOREIGN KEY (user_id) REFERENCES user_basic(user_id)
);

总结要点

约束确保数据完整性

设计平衡范式与性能

索引是双刃剑

考虑未来发展

文档化设计决策

相关推荐