唯一约束核心特性

1. 唯一性保证:确保列中所有值都是唯一的

2. NULL值处理:允许NULL值,但只能有一个NULL(因为NULL不等于NULL)

3. 多列约束:一个表可以有多个唯一约束

4. 索引自动创建:MySQL会自动为唯一约束列创建唯一索引

5. 与主键区别:

    主键不允许NULL,唯一约束允许

    每表只能有一个主键,但可有多个唯一约束

    主键通常用于标识记录,唯一约束用于业务唯一性

 

唯一约束操作详解

创建表时定义唯一约束

单列唯一约束:

CREATE TABLE users (
    user_id INT PRIMARY KEY,
    username VARCHAR(50) UNIQUE,
    email VARCHAR(100) UNIQUE
);

 

多列组合唯一约束:

CREATE TABLE product_variants (
    product_id INT,
    color VARCHAR(20),
    size VARCHAR(10),
    PRIMARY KEY (product_id, color, size),
    UNIQUE KEY (product_id, color)  -- 特定组合必须唯一
);

 

修改表添加唯一约束

 添加单列唯一约束

ALTER TABLE employees ADD CONSTRAINT uk_employee_email UNIQUE (email);

 添加多列组合唯一约束

ALTER TABLE orders ADD CONSTRAINT uk_order_customer_date UNIQUE (customer_id, order_date);


删除唯一约束

ALTER TABLE users DROP INDEX uk_user_email;

注意:在MySQL中唯一约束是通过索引实现的,所以使用`DROP INDEX`而非`DROP CONSTRAINT`

 

唯一约束高级特性

唯一约束与NULL值

 唯一约束允许NULL值

 可以有多个NULL值(因为NULL不等于NULL)

 若需要确保NULL也是唯一的,可添加NOT NULL约束

CREATE TABLE departments (
    dept_id INT PRIMARY KEY,
    dept_code VARCHAR(10) NOT NULL UNIQUE  -- 不允许NULL
);

 

条件唯一约束(MySQL 8.0+)

使用函数索引创建条件唯一约束:

 只对非删除记录强制唯一

CREATE TABLE products (
    id INT PRIMARY KEY,
    name VARCHAR(100),
    is_deleted TINYINT DEFAULT 0,
    UNIQUE KEY uk_product_name (name, (IF(is_deleted=1, NULL, 1)))
);

 

唯一约束与外键

唯一约束可以作为外键的引用目标:

CREATE TABLE users (
    user_id INT PRIMARY KEY,
    username VARCHAR(50) UNIQUE
);
CREATE TABLE user_profiles (
    profile_id INT PRIMARY KEY,
    username VARCHAR(50),
    FOREIGN KEY (username) REFERENCES users(username)
);

 

唯一约束最佳实践

1. 命名规范:使用`uk_表名_列名`的命名约定

2. 业务逻辑:

    为业务上需要唯一的字段添加约束(如邮箱、手机号)

    避免过度使用,影响插入性能

3. 性能考虑:

    唯一约束会自动创建索引,提高查询速度

    但会降低插入和更新性能(需要检查唯一性)

4. 错误处理:

    捕获并处理`ER_DUP_ENTRY`错误(错误代码1062)

    提供用户友好的重复值提示

 

实际应用示例

用户管理系统:

CREATE TABLE users (
    user_id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) NOT NULL UNIQUE,
    email VARCHAR(100) NOT NULL UNIQUE,
    phone VARCHAR(20) UNIQUE,  -- 允许NULL
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

 

添加复合唯一约束

ALTER TABLE user_roles ADD CONSTRAINT uk_user_role 
UNIQUE (user_id, role_id);

 

商品库存系统:

CREATE TABLE products (
    product_id INT AUTO_INCREMENT PRIMARY KEY,
    sku VARCHAR(20) NOT NULL UNIQUE,
    name VARCHAR(100) NOT NULL,
    UNIQUE KEY uk_product_name_brand (name, brand_id)
);
 
CREATE TABLE inventory (
    warehouse_id INT,
    product_id INT,
    quantity INT NOT NULL,
    PRIMARY KEY (warehouse_id, product_id),
    UNIQUE KEY uk_product_location (product_id, location_code)
);

 

常见问题解决方案

1. 忽略重复值插入:

INSERT IGNORE INTO users (username, email) VALUES ('john', 'john@example.com');

    或者 

 INSERT INTO users (username, email) 
   VALUES ('john', 'john@example.com')
   ON DUPLICATE KEY UPDATE last_seen = NOW();

2. 替换重复记录:

  

 REPLACE INTO users (user_id, username, email) 
   VALUES (1, 'john', 'john@example.com');

 

3. 批量插入处理重复:

 

  INSERT INTO products (sku, name)
   VALUES ('SKU001', 'Product 1'), ('SKU002', 'Product 2')
   ON DUPLICATE KEY UPDATE name = VALUES(name);
点赞(1)

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

Dotcpp在线编译      (登录可减少运行等待时间)