MySQL中的唯一性约束与NULL详解

作者:Giraffe 时间:2024-01-13 10:24:10 

前言

之前做的一个需求,简化描述下就是接受其他组的 MQ 的消息,然后在数据库里插入一条记录。为了防止他们重复发消息,插入多条重复记录,所以在表中的几个列上加了个唯一性索引。


CREATE UNIQUE INDEX IDX_UN_LOAN_PLAN_APP ON testTable (A, B, C);

这时 A,B,C 三列都是不允许 NULL 值的,唯一性约束也是 work 的。

后来由于需求的变化,修改了以前的唯一性约束,又多加了一列。(至于为什么加就不赘述了)。


ALTER TABLE testTable
DROP INDEX IDX_UN_LOAN_PLAN_APP,
ADD UNIQUE KEY `IDX_UN_LOAN_PLAN_APP` (A, B, C, D);

新加的 D 是类型是 datetime, 允许为 NULL,默认值为 NULL。之所以默认值为 NULL,是考虑到不是所有记录都有这个时间的, 如果强行设置一个 Magic Value (比如'1970-01-01 08:00:00‘)当做默认值,看起来很奇怪。

蓝后。。。就出问题了。加了 D 之后,唯一性约束基本就失效了。


Insert into testTable (A,B,C,D) VALUES (1,2,3,NULL); --- OK
Insert into testTable (A,B,C,D) VALUES (1,2,3,NULL); --- OK
Insert into testTable (A,B,C,D) VALUES (1,2,3,NULL); --- OK

上面的三条 SQL 都是可以执行成功的,数据库中会有多条一样的记录。可按照我们以前的构想,在执行后两条 SQL 时 应该抛出 ‘Duplicate key' 的异常的。

后来查了一下,才发现其实 MySQL 官方文档上已经明确说了这一点, 唯一性索引是允许多个 NULL 值的存在的:


A UNIQUE index creates a constraint such that all values in the index must be distinct. An error occurs if you try to add a new row with a key value that matches an existing row. For all engines, a UNIQUE index allows multiple NULL values for columns that can contain NULL.

从下表中也可以看出来不管是采用什么类型的存储引擎,在建立 unique key 的时候都是允许多个 NULL 存在的。。。。

MySQL中的唯一性约束与NULL详解

细想想,其实也蛮合理,毕竟在 MySQL 中认为 NULL 代表着“未知”。 在 SQL 中,任何值与 NULL 的比较返回值都是 NULL 而不是 TRUE, 就算 NULL 与 NULL 的比较也是返回 NULL。

所以只能 fix 了。。。解决办法也蛮简单粗暴的,直接把线上数据刷了一遍,将“1970-01-01 08:00:00”作为默认值,然后把那列改为不允许为 NULL 的了,咳咳。

MySQL 官网上也有蛮多人讨论过这个问题,一部分人认为这是 MySQL 的 bug, 另一部分则认为是一个 feature,附上链接。

MySQL Bugs: #8173: unique index allows duplicates with null values

来源:http://yemengying.com/2017/05/18/mysql-unique-key-null/

标签:mysql,唯一性约束,null
0
投稿

猜你喜欢

  • sql server 表结构修改方法

    2024-01-16 15:51:40
  • ASP四级连动下拉列表程序段

    2009-07-03 15:33:00
  • 基于Python制作公交车站查询系统

    2022-10-03 04:34:03
  • SQLServer中数据库文件的存放方式,文件和文件组

    2024-01-25 21:38:25
  • pandas中DataFrame修改index、columns名的方法示例

    2022-02-14 15:42:37
  • 15行Python代码实现免费发送手机短信推送消息功能

    2023-11-01 10:20:51
  • Python pandas处理缺失值方法详解(dropna、drop、fillna)

    2023-04-03 03:45:36
  • MySQL存储文本和图片的方法

    2024-01-12 17:56:03
  • 零基础写python爬虫之使用urllib2组件抓取网页内容

    2021-08-16 01:13:22
  • python爬虫scrapy框架的梨视频案例解析

    2023-01-16 08:22:19
  • 一篇文章搞懂Python Unittest测试方法的执行顺序

    2023-11-01 09:38:01
  • Python实现葵花8号卫星数据自动下载实例

    2021-09-26 13:40:25
  • Python直接赋值与浅拷贝和深拷贝实例讲解使用

    2021-06-16 08:21:21
  • Pycharm安装第三方库时Non-zero exit code错误解决办法

    2023-03-15 12:15:01
  • python编写WAF与Sqlmap结合实现指纹探测

    2022-05-23 08:10:17
  • Python脚本实现格式化css文件

    2023-01-09 19:00:37
  • 如何显示数据库里的图片?

    2010-06-08 09:36:00
  • python实现一个简单的udp通信的示例代码

    2023-07-23 16:08:43
  • sqlserver分页查询处理方法小结

    2024-01-13 19:50:23
  • Python函数生成器原理及使用详解

    2023-12-02 17:57:31
  • asp之家 网络编程 m.aspxhome.com