Mysql数据唯一约束与唯一索引案例总结及踩坑记(含NULL值与唯一约束唯一索引的搭配使用)

Posted ShenLiang2025

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mysql数据唯一约束与唯一索引案例总结及踩坑记(含NULL值与唯一约束唯一索引的搭配使用)相关的知识,希望对你有一定的参考价值。

Mysql数据唯一索引与唯一约束案例总结

唯一约束的说明

唯一约束是约束(CONSTRAINT)里的一种,常见的还有主键、外检、默认值、是否为空、检查等。唯一约束即限制某个或某些字段具有唯一性(不能重复)。

唯一索引的说明

唯一索引是只允许索引中的每个值对应记录的一行,这就像身份标识一样,每个人都只有一个。

代码验证

创建表时指定唯一约束

CREATE TABLE tb_unique
(id int,
name varchar(20) UNIQUE,
addr varchar(30),
age int
)

:1 当某个字段被指定为UNIQUE时会自动产生唯一索引。
       2 在某个字段定义为唯一时还可以通过修改表时对该字段再次定义为UNIQUE,不过这显然没太大意义。再SHOW INDEX FROM tablename时可查看到多个关于该字段UNIQUE的重复定义。

创建表时指定复合多字段唯一约束

CREATE TABLE tb_unique2
(id int,
name varchar(20),
addr varchar(30),
age int,
PRIMARY key(id),
UNIQUE KEY com_nameadrr (name,addr),
KEY age (age)
)

:1 这里的KEY age(age)意为普通索引。可通过查看索引命令SHOW INDEX FROM tablename命令查看,详细的见查看索引部分。

通过数据字典查看表的约束

select * FROM information_schema.TABLE_CONSTRAINTS
WHERE TABLE_NAME='tb_unique' AND CONSTRAINT_TYPE='UNIQUE'

/* 结果
CONSTRAINT_CATALOG     CONSTRAINT_SCHEMA       CONSTRAINT_NAME    TABLE_SCHEMA    TABLE_NAME       CONSTRAINT_TYPE
def  shenl      name      shenl      tb_unique      UNIQUE

*/

通过修改表创建唯一约束

ALTER TABLE tb_unique ADD CONSTRAINT cons_uniquename UNIQUE(addr);
select * FROM information_schema.TABLE_CONSTRAINTS
WHERE TABLE_NAME='tb_unique' AND CONSTRAINT_TYPE='UNIQUE'

/* 结果
CONSTRAINT_CATALOG     CONSTRAINT_SCHEMA       CONSTRAINT_NAME    TABLE_SCHEMA    TABLE_NAME       CONSTRAINT_TYPE
def  shenl      name      shenl      tb_unique      UNIQUE
def  shenl      cons_uniqueaddr  shenl      tb_unique      UNIQUE
*/

创建表时指定唯一索引

CREATE TABLE tb_uniqueidx
(id int,
name varchar(20) UNIQUE,
addr varchar(30),
age int,
UNIQUE INDEX idx_name(name(20) ASC)
)


-- 通过show create table查看表创建脚本。
show create table tb_uniqueidx;
/* 结果
Table     Create Table
tb_uniqueidx CREATE TABLE `tb_uniqueidx` (
  `id` int(11) DEFAULT NULL,
  `name` varchar(20) DEFAULT NULL,
  `addr` varchar(30) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  UNIQUE KEY `name` (`name`),
  UNIQUE KEY `idx_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3
*/

-- 约束里查看查看Unique和索引信息。
select * FROM information_schema.TABLE_CONSTRAINTS
WHERE TABLE_NAME='tb_uniqueidx' AND CONSTRAINT_TYPE='UNIQUE'
/*结果
CONSTRAINT_CATALOG   CONSTRAINT_SCHEMA    CONSTRAINT_NAME TABLE_SCHEMA  TABLE_NAME       CONSTRAINT_TYPE
def  shenl      name     shenl      tb_uniqueidx UNIQUE
def  shenl      idx_name      shenl      tb_uniqueidx UNIQUE
*/

修改表时指定唯一索引

CREATE UNIQUE INDEX idx_addr ON tb_uniqueidx (addr (30) DESC);
ALTER TABLE tb_uniqueidx ADD UNIQUE INDEX idx_addr2 (addr (30) DESC);
-- 通过key关键字和index效果一样。
ALTER TABLE tb_uniqueidx ADD UNIQUE KEY idx_addr2 (addr (30) DESC);

查看索引信息

show index from tb_unique2

/* 部分结果
tb_unique2    0     PRIMARY       1     id
tb_unique2    0     com_nameadrr     1     name
tb_unique2    0     com_nameadrr     2     addr
tb_unique2    1     age  1     age
*/

删除索引

DROP INDEX idx_addr ON tb_uniqueidx
alter table tb_uniqueidx drop index idx_addr2;

唯一索引与NULL

CREATE TABLE tb_uniqueidx
(id int,
name varchar(20) UNIQUE,
addr varchar(30),
age int,
PRIMARY KEY(id),
UNIQUE INDEX idx_name(addr(30) ASC)
)

-- 插入多条为NULL的值到建立唯一索引的字段里
INSERT INTO tb_uniqueidx VALUES(1,'Tom','Shanghai',30);
INSERT INTO tb_uniqueidx VALUES(2,'Tim',NULL,40);
INSERT INTO tb_uniqueidx VALUES(3,'John',NULL,40);

由此可见唯一索引对NULL值是免疫的,即并不能约束它(NULL)。

触发器约束唯一索引里的NULL

-- 通过约束只能输入一次NULL值,触发器需要在表没有数据时即创建。
CREATE TRIGGER trg_tb_uniqueidx
BEFORE INSERT ON tb_uniqueidx
FOR EACH ROW
BEGIN
DECLARE v_errmsg, v_value text;
IF EXISTS(SELECT 1 FROM tb_uniqueidx WHERE addr <=> NEW.addr) THEN
IF NEW.addr IS NULL THEN
SET v_value = 'NULL';
ELSE
SET v_value = CONCAT('''', NEW.addr, '''');
END IF;
SET v_errmsg = CONCAT('重复的值 ',v_value,' 出现在字段 addr 里');
SIGNAL SQLSTATE '23000'
SET MESSAGE_TEXT = v_errmsg,
mysql_ERRNO = 1062;
END IF;
END

-- 当我们再次插入NULL值时则会报错。
INSERT INTO tb_uniqueidx VALUES(4,'Kate',NULL,50);

NOT NULL结合UNIQUE一起使用

该方法即将NOT NULL和UNIQUE约束一起使用。

CREATE TABLE tb_uniqueidx
(id int,
name varchar(20) UNIQUE,
addr varchar(30) NOT NULL UNIQUE,
age int,
PRIMARY KEY(id),
UNIQUE INDEX idx_name(addr(30) ASC)
)

以上是关于Mysql数据唯一约束与唯一索引案例总结及踩坑记(含NULL值与唯一约束唯一索引的搭配使用)的主要内容,如果未能解决你的问题,请参考以下文章

nSQLServer与MySQL约束/索引命名的一些差异总结

SQLServer 唯一键约束和唯一索引有啥区别

mongodb 索引唯一性约束

MYSQL中唯一约束和唯一索引的区别

mysql/mariadb知识点总结 之 约束管理索引管理键管理语句

mysql/mariadb知识点总结 之 约束管理索引管理键管理语句