PostgreSQL更新拼接列时原有值被置空问题咨询
这问题我碰到过好多次了,核心原因其实是PostgreSQL里concat()函数的特性——只要传入的任意一个参数是NULL,整个拼接结果就会直接变成NULL。你原来的表中肯定存在某一行的estu_nacimiento_dia、estu_nacimiento_mes或者estu_nacimiento_anno字段是NULL值,导致整行的拼接结果直接为空。针对你遇到的两种场景,分别给你解决方案:
场景1:日期字段拼接变NULL
方案1:使用concat_ws()自动忽略NULL值
concat_ws()是“concat with separator”的缩写,它会自动跳过NULL参数,只拼接非NULL的部分,完美解决你的问题:
UPDATE saber2012_1 SET estu_fecha_nacimiento = concat_ws('/', estu_nacimiento_dia, estu_nacimiento_mes, estu_nacimiento_anno);
比如如果某行的estu_nacimiento_dia是NULL,结果会变成/12/2000(如果月和年有值的话),不会直接变成NULL。
方案2:用coalesce()给NULL字段设默认值(严格格式需求)
如果你需要确保日期格式是完整的日/月/年,不想出现缺省的分隔符,可以用coalesce()给每个可能为NULL的字段设置默认值,同时注意把整数类型的字段转成文本类型(避免拼接报错):
UPDATE saber2012_1 SET estu_fecha_nacimiento = concat( coalesce(estu_nacimiento_dia::text, '00'), '/', coalesce(estu_nacimiento_mes::text, '00'), '/', coalesce(estu_nacimiento_anno::text, '0000') );
这样NULL的字段会被替换成00或0000,保证拼接结果始终是完整格式的字符串。
场景2:新增int字段后更新变NULL
这个问题的根源和上面一样——你更新时使用的表达式中存在NULL值(比如从其他可能为NULL的字段计算而来),而整数类型无法存储NULL(除非你特意设置允许NULL,但显然你不想要这个结果)。解决方法同样用coalesce()给计算结果设置默认值:
-- 示例:假设你从punt_naturales1和punt_naturales2求和得到新字段 UPDATE saber2012_uno SET punt_c_naturales = coalesce(punt_naturales1 + punt_naturales2, 0);
这样如果求和的结果是NULL(比如其中一个字段为NULL),就会自动替换成0,不会让新字段变成NULL。
额外排查建议
你可以先查询表中哪些行存在NULL值,方便后续处理:
SELECT * FROM saber2012_1 WHERE estu_nacimiento_dia IS NULL OR estu_nacimiento_mes IS NULL OR estu_nacimiento_anno IS NULL;
如果这些NULL值是数据缺失导致的,你可以先补全数据再执行更新,效果会更理想。
内容的提问来源于stack exchange,提问作者juancamilovallejos0

