在MySQL日常数据处理中,经常遇到需要把某个字段的原有内容后面接上一段新字符串的情况,比如给账号追加后缀、在备注后补充处理时间等。这类需求用一条UPDATE语句就能完成,核心在于正确使用字符串函数。

一、使用CONCAT函数追加字符串
CONCAT是MySQL最常用的字符串拼接函数,它接受多个参数,按顺序把它们连接成一个字符串。当我们想向某字段追加内容时,可以把字段名和新字符串作为参数传入,再用UPDATE赋值给原字段。
需要注意,如果原字段值为NULL,CONCAT的返回结果也会是NULL,这会导致更新后该字段变成空值而不是拼接结果。因此生产环境通常要配合IFNULL或COALESCE处理空值。下面示例给user表的email字段统一追加域名:
UPDATE user SET email = CONCAT(IFNULL(email, ''), '@ipipp.com') WHERE id > 100;
上面的语句中,IFNULL(email, '')保证即使email为NULL也会从空字符串开始拼接,避免整列被置空。WHERE条件限制了只处理id大于100的记录,是一种安全的写法。
CONCAT函数的优势是语法直观、几乎所有MySQL版本都支持;缺点是参数较多时可读性一般,且对NULL敏感。在明确字段不可能为NULL的场景下,可以省略IFNULL直接拼接。
二、使用CONCAT_WS函数处理分隔符
如果追加的内容需要和原值用特定分隔符隔开,比如用逗号连接标签,CONCAT_WS会更方便。WS代表with separator,第一个参数是分隔符,后面是要拼接的字段或字符串。
与CONCAT不同,CONCAT_WS会忽略NULL值而不是整体返回NULL,这在追加可选信息时很实用。以下示例在remark字段后追加处理人,用竖线分隔:
UPDATE orders
SET remark = CONCAT_WS('|', remark, 'handled_by_admin')
WHERE status = 'pending';
假设某行remark原本是NULL,CONCAT_WS会直接得到handled_by_admin,不会多出前面的竖线。这种特性让数据更整洁。
不过CONCAT_WS只在需要统一分隔符时优势明显,如果只是简单末尾加固定串,用CONCAT更轻量。两者都要注意字符集,若原字段和拼接串编码不一致可能产生乱码,建议表级统一为utf8mb4。
三、利用表达式与函数组合实现复杂追加
实际业务中追加逻辑可能更复杂,例如只在字段不包含某子串时才追加,或追加当前时间。这时可以结合LOCATE、NOW等函数。
下面例子给未带手机号标识的customer表的info字段追加登记时间,且用IF避免重复添加:
UPDATE customer
SET info = IF(LOCATE('reg:', info) > 0, info, CONCAT(info, ' reg:', NOW()))
WHERE info IS NOT NULL;
LOCATE返回子串位置,大于0表示已存在,此时不拼接。NOW()生成当前时间戳,让追加内容具有时效性。这种写法在数据清洗中非常有用。
从性能看,在大数据表上做字符串函数更新会锁行并写日志,应在低峰期执行,并尽量通过主键或索引字段缩小WHERE范围。若需更新百万级数据,建议分批次用LIMIT提交,防止长事务。
四、常见错误与注意事项
新手常直接写SET col = col + 'abc',但MySQL里加号是算术运算符,字符串会被转成数字,结果往往为0。必须使用CONCAT系列函数。
还有人忘记WHERE条件导致全表更新,在正式库操作前务必先用SELECT确认影响行数:
SELECT id, CONCAT(info, '_tmp') AS new_info FROM logs WHERE create_date < '2023-01-01';
确认无误后再改写成UPDATE。另外,若字段是TEXT类型且超长,拼接后超过定义长度会被截断,需提前评估数据大小。
总结来说,MySQL向字段追加字符串主要依靠UPDATE加CONCAT或CONCAT_WS,处理好NULL与分隔符,控制更新范围,就能稳妥完成各类字符串扩展需求。