PostgreSQL中唯一约束对null值失效

458 阅读1分钟

问题

复工开发第一天,发现离线调度的表出现问题,产生大量相同的空值维表数据,该表以(evttime,shopid,devicecode)作为唯一约束条件,正常情况下不会出现这种情况。

image.png

原因

那么是什么情况导致了唯一约束呢?上网查询后发现PostgreSQL中判断null=null的返回值为null,这个意思就是说null值之间的判断会导致唯一约束认为并不是相同的值,导致离线调度插入的数据有重复(我们的视角)。

解决目标

保证离线调度正确执行的同时,解决多个空值同时存在的问题。

尝试解决方案

1.通过对表建立唯一索引去解决

CREATE UNIQUE INDEX save_devicecode ON s_dwd_cz301.dwd_cz301_11_opc(devicecode) WHERE evttime is NULL AND shopid is NULL;

这样做的结果是能够保证在其他字段值为空时,所建索引保证值唯一,但是在对该表插入以上相同空数据时,会产生报错,导致整个调度失败,这并不符合我们的预期目的。

2.更改逻辑,为产生的空值赋予默认值

case when evt_time is null then '1970-01-01 08:00:00.000' 
else evt_time end as evttime,
case when shop_id is null then -1 
else shop_id end as shopid

这样做的好处是保证空值产生唯一,但产生值需与下游沟通符合要求。

image.png

新年第一个bug,在这里记录。若您有更好的方法解决以上问题,欢迎留言交流。

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 1 天,点击查看活动详情