SQL Server更新同列多个值的最优方法 如何避免Art与Art History替换冲突
问题解答
针对问题1:单条语句完成多值替换方案
推荐使用字符串拆分+映射表关联+合并的方案,仅需1次更新即可完成所有替换,不需要写多条replace语句,也不受替换顺序影响,后续新增映射规则只需修改映射配置即可,不用调整SQL结构。
示例代码(适配SQL Server 2016及以上版本):
WITH SubjectMapping AS ( -- 统一维护学科和编码的映射关系 SELECT * FROM (VALUES ('Math', '001'), ('English', '002'), ('Art', '003'), ('Art History', '004') ) t(subject, code) ), ClassSplitMapping AS ( SELECT sc.name, sc.class AS original_class, STRING_AGG(sm.code, ';') AS new_class FROM StudentClass sc -- 按分号拆分class字段为独立的单个学科 CROSS APPLY STRING_SPLIT(sc.class, ';') s -- 精确匹配学科对应的编码 LEFT JOIN SubjectMapping sm ON s.value = sm.subject GROUP BY sc.name, sc.class ) -- 单次更新完成所有编码替换 UPDATE s SET s.class = sp.new_class FROM StudentClass s JOIN ClassSplitMapping sp ON s.name = sp.name AND s.class = sp.original_class
针对问题2:避免包含关系字符串替换冲突的方案
除了调整替换顺序外,有两种更稳妥的方案可以从根源规避子串误匹配问题:
- 精确匹配方案:就是上述拆分后再匹配的方案,每个学科都是独立单元做精确匹配,不会出现子串匹配的误替换,是优先推荐的解决方案。
- 带分隔符替换方案:如果不想做字符串拆分,可以给替换内容补充分隔符避免匹配到子串,不需要调整替换顺序,示例如下:
-- 先给class首尾都加分隔符,统一匹配规则 UPDATE StudentClass SET class = CONCAT(';', class, ';'); -- 所有替换都带分隔符匹配,;Art; 不会匹配到 ;Art History; 中的子串 UPDATE StudentClass SET class = REPLACE(class, ';Math;', ';001;'); UPDATE StudentClass SET class = REPLACE(class, ';English;', ';002;'); UPDATE StudentClass SET class = REPLACE(class, ';Art;', ';003;'); UPDATE StudentClass SET class = REPLACE(class, ';Art History;', ';004;'); -- 最后去掉首尾额外添加的分隔符 UPDATE StudentClass SET class = SUBSTRING(class, 2, LEN(class)-2);
内容的提问来源于stack exchange,提问作者razzberry
相关产品推荐
相关产品推荐

