MySQL 中 NULL 导致唯一键失效
最近遇到一个问题,我为一张表中创建了一个唯一键,并且键中字段为NULL
,最终导致了唯一约束失效。这里做下分析:
首先新建一张表,包含 work_no
,name
,age
三个字段:
DROP TABLE IF EXISTS t_emp;
CREATE TABLE t_emp(id int(8) not null auto_increment,work_no varchar(8) comment '工号',name varchar(255) comment '姓名',age int(3) comment '年龄',primary key(id),unique key(work_no,name,age)
)engine=InnoDB,charset=UTF8mb4,comment="员工表";
从创建语句中我们可以看到,我们为工号,姓名,年龄上添加了唯一约束,现在我们尝试插入数据:
insert into t_emp(work_no,name,age) values ('9527','张三',23);
insert into t_emp(work_no,name,age) values ('9527','张三',23);
我们在尝试插入第二条数据时会报错:
(1062, “Duplicate entry ‘9527-张三-23’ for key ‘work_no’”)
可见唯一键是生效了的,现在我们尝试将 age 为 null 再次尝试下:
insert into t_emp(work_no,name,age) values ('9527','张三',NULL);
insert into t_emp(work_no,name,age) values ('9527','张三',NULL);
可以看到当 age 为空时附加在该字段上的唯一约束失效了。
首先我们可以确认 null 值的出现破坏了唯一性,原本应该被唯一约束限制到的记录被插入到了表中。
如何确保 NULL
不破坏唯一性?
- 不允许列出现
NULL
值,即NOT NULL
- 给列增加
DEFUALT
值,注意DEFAULT
不能是NULL
所以需要调整建表语句:
DROP TABLE IF EXISTS t_emp;
CREATE TABLE t_emp(id int(8) not null auto_increment,work_no varchar(8) NOT NULL DEFAULT '' comment '工号',name varchar(255) NOT NULL DEFAULT '' comment '姓名',age int(3) NOT NULL DEFAULT 0 comment '年龄',primary key(id),unique key(work_no,name,age)
)engine=InnoDB,charset=UTF8mb4,comment="员工表";
简单来说就是不要在唯一约束上使用 NULL
,但是空字符串是可以的。
如果我们再继续寻找其根本原因的话,就要探究 NULL 在 MySQL 中的实现原理了。
深度探讨
关于NULL 值是否应该被唯一约束限制到的问题,早年有人向 MySQL 开发提出过问题。具体可以参考文档,可以看到开发者给出的解释是:
感兴趣的童鞋可以点进去看下,关于这个问题是否是一个BUG 的问题探讨的还是很激烈的。最终结果还是显而易见的,MySQL 保留了空值不受唯一约束的限制的这个特性。开发者通过调整空值为空字符串来处理该类异常问题。
NULL 与 NULL 不相等
还记得在 MySQL 中如何以字段值为 NULL 作为条件查询吗?
SELECT * FROM t_emp WHERE age IS NULL;
NULL 在 MySQL 中作为一个特殊的存在,我们无法使用平常使用的等值查询进行查询:
MySQL root@localhost:test> select null = null;
|| null = null ||
| <null> |
1 row in set
Time: 0.001s
MySQL root@localhost:test> SELECT NULL IS NULL;
|| NULL IS NULL ||
| 1 |
1 row in set
Time: 0.001s
比如我们有一个单列的唯一索引,既然实际会有空值的情况,如果唯一约束对空值也有起作用,就会导致仅有一行数据可以为空,这可能会和实际的业务需求相冲突的。所以通常MySQL的存储引擎的唯一索引对NULL值是不适用的。 这也就倒是联合唯一索引的情况下,只要某一列为空,就不会报唯一索引冲突。
或者说,我们一般认为在 MySQL 中 NULL 是一个没有被赋值的值,既然没有被赋值,那么它就有可能被赋值为任意值。这样就可以理解为两个任意值不相等,也就是两个 NULL 值是不相等的,因此也就可以在 唯一索引中单独存在了。
面试题:主键索引与唯一索引的区别
- 唯一索引的索引列允许空值,而主键索引的列不允许空值
- 唯一索引列存在空值时,唯一约束对空值时不生效的
- 主键索引可以被引用为外键,而唯一索引不能
- 一个表中最多只能创建一个主键索引,单可以创建多个唯一索引
主键索引
= 唯一索引
+ 唯一约束
+ 非空约束
唯一索引
= 唯一索引
+ 唯一约束
参考资料
MySQL: 唯一索引与NULL
Mysql 唯一索引的字段值
Bug #8173 unique index allows duplicates with null values
MySQL 中 NULL 导致唯一键失效相关推荐
- MySQL 中NULL和空值的区别?
做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 01 小木的故事 作为后台开发,在日常工作中如果要接触Mysql数据库,那么不可避免会遇到Mysql中的NULL和空值.那 ...
- MySQL并发insert因唯一键导致的DeadLock
业务场景为:一个业务中向A表插入数据多条,同时向B表插入多条纪录,两张表都有组合唯一键,使用jmeter进行并发测试时出现死锁现象! <==== 一个业务同时向两张表中插入数据,同样的组合唯一索 ...
- mysql主键和唯一键的区别
什么是主键? 主键是表中唯一标识该表中每个元组(行)的列.主键对表实施完整性约束.表中只允许使用一个主键.主键不接受任何重复值和空值.表中的主键值很少更改,因此在选择主键是需要小心,要选择很少发生更改 ...
- mysql''和null,mysql中NULL和null的区别
接触php的web开发一段时间了,在进行数据库操作的时候经常会遇到一个问题,使得同一字段在页面显示时有3种类型NULL,null以及数字,当时的解决办法是将这一字段定义为varchar类型,在插入数据 ...
- MySQL从入门到精通50讲(十)-MySQL中null值如何处理
MySQL NULL 值处理 我们已经知道MySQL使用 SQL SELECT 命令及 WHERE 子句来读取数据表中的数据,但是当提供的查询条件字段为 NULL 时,该命令可能就无法正常工作. 为了 ...
- mysql中的钱null,mysql 中null总结
====================== 相信很多用了mysql很久的人,对这两个字段属性的概念还不是很清楚,一般会有以下疑问: 1.我字段类型是not null,为什么我可以插入空值 2.为毛n ...
- MySQL 中NULL和空值的区别
平时我们在使用MySQL的时候,对于MySQL中的NULL值和空值区别不能很好的理解.注意到NULL值是未知的,且占用空间,不走索引,DBA建议建表的时候最好设置字段是NOT NULL 来避免这种低效 ...
- mysql中null值求和_sql求和涉及到null值
SQL ISNULL().NVL().IFNULL() 和 COALESCE() 函数 请看下面的 "Products" 表: P_Id ProductName UnitPrice ...
- 在MySQL中 NULL的含义是_mysql null的含义是什么
mysql null的含义:1.如在普通的字段中,空值就是表示空值:2.如果将一个空值的数据插入到TimesTamp类型的字段中,空值就不一定为空. mysql null的含义: 空值是不占用空间的, ...
最新文章
- 职场社交:做职场版微信不如做职场版微博
- 数据浪潮上的IP雄鹰
- SimBERTv2来了!融合检索和生成的RoFormer-Sim模型
- Leetcode怎么调试java代码,IDEA2020.1使用LeetCode插件运行并调试本地样例的方法详解...
- Wireshark数据包分析(一)——使用入门
- 一文读懂区块链以及一个区块链的实现
- 【STM32】【STM32CubeMX】STM32CubeMX的使用之八:低功耗模式及MCU唤醒
- Linux的触屏手势软件安装,如何添加Mac的多点触控手势到Ubuntu | MOS86
- 2.7配置自定义的Formatters
- 7月25日训练赛签到题HDU1257
- OpenGL 驱动 与 扩展的关系
- pyecharts源码解读(15)图表类包charts之组合图表: 选项卡Tab
- 2022 职业院校移动开发总结(uni-app)
- happen-before原则
- android PMU
- 请问现在好多抖音巨量广告落地页pages.tmall.com的页面如何生成
- 标签打印软件如何设置打印区域
- queue.queue是什么
- storage/emulated/0.到底在哪儿
- JasperReports初体验
热门文章
- 设置Symantc内部LiveUpdate服务器注意事项
- oppo锁频段_给大家科普下现在的OPPO Reno3支持哪几个5G频段
- 如何计算黄金分割比例
- qt linux获取安装目录路径
- Selenium IDE使用指南四(代码导出)
- 想要创业,注册公司需要什么流程和资料?
- 深度学习在医学图像处理中的应用
- SWUST OJ#1051(数据结构之输出利用先序遍历创建的二叉树中的指定结点的Child结点)
- 2021全新改版影视app系统源码(全开源)
- 有一种胸襟,叫“我搭台 你唱戏” 有一种气魄,叫“我做平台 大家赚钱”