在SQL的实际使用中,处理字符串里的重复字符是常见需求,比如用户填写的地址里重复了多个相同的区号,或者商品名称里出现了重复的修饰词,这些都需要通过字符串函数完成去重操作。不同数据库的内置函数存在差异,对应的实现方式也有所不同。

通用思路:利用替换函数逐次去重
大部分数据库都提供了REPLACE字符串函数,它的作用是把字符串中指定的子串替换成新的内容。我们可以基于这个函数,遍历字符串里的每个字符,把重复出现的字符替换成空串,从而实现去重。核心逻辑是先拆分字符串得到所有单个字符,再判断每个字符是否已经在结果字符串里存在,不存在就拼接,存在就跳过。
MySQL场景下的实现
MySQL没有内置的字符串拆分函数可以直接把字符串拆成单个字符的集合,但是可以通过自定义变量配合循环来实现。下面的示例会处理test_str表里的content字段,去掉其中的重复字符。
-- 创建测试表
CREATE TABLE test_str (
id INT PRIMARY KEY AUTO_INCREMENT,
content VARCHAR(100)
);
-- 插入测试数据
INSERT INTO test_str (content) VALUES ('aabbccddeeff'), ('1122334455'), ('hello_world_hello');
-- 去掉重复字符的存储过程
DELIMITER //
CREATE PROCEDURE remove_duplicate_char()
BEGIN
DECLARE v_id INT;
DECLARE v_content VARCHAR(100);
DECLARE v_result VARCHAR(100) DEFAULT '';
DECLARE v_len INT;
DECLARE v_i INT DEFAULT 1;
DECLARE v_char CHAR(1);
DECLARE done INT DEFAULT 0;
-- 定义游标遍历所有记录
DECLARE cur CURSOR FOR SELECT id, content FROM test_str;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN cur;
read_loop: LOOP
FETCH cur INTO v_id, v_content;
IF done THEN
LEAVE read_loop;
END IF;
-- 重置结果和循环变量
SET v_result = '';
SET v_i = 1;
SET v_len = CHAR_LENGTH(v_content);
-- 遍历每个字符
WHILE v_i <= v_len DO
SET v_char = SUBSTRING(v_content, v_i, 1);
-- 判断字符是否已经在结果里
IF INSTR(v_result, v_char) = 0 THEN
SET v_result = CONCAT(v_result, v_char);
END IF;
SET v_i = v_i + 1;
END WHILE;
-- 更新去重后的结果
UPDATE test_str SET content = v_result WHERE id = v_id;
END LOOP;
CLOSE cur;
END //
DELIMITER ;
-- 调用存储过程
CALL remove_duplicate_char();
-- 查看结果
SELECT * FROM test_str;
SQL Server场景下的实现
SQL Server可以通过自定义函数结合循环逻辑实现字符串去重,下面的示例创建了一个自定义函数fn_remove_duplicate,接收字符串参数返回去重后的结果。
-- 创建测试表
CREATE TABLE test_str (
id INT IDENTITY(1,1) PRIMARY KEY,
content NVARCHAR(100)
);
-- 插入测试数据
INSERT INTO test_str (content) VALUES ('aabbccddeeff'), ('1122334455'), ('hello_world_hello');
-- 创建去重函数
CREATE FUNCTION fn_remove_duplicate (@str NVARCHAR(100))
RETURNS NVARCHAR(100)
AS
BEGIN
DECLARE @result NVARCHAR(100) = '';
DECLARE @len INT = LEN(@str);
DECLARE @i INT = 1;
DECLARE @char NCHAR(1);
WHILE @i <= @len
BEGIN
SET @char = SUBSTRING(@str, @i, 1);
-- 判断字符是否已在结果中
IF CHARINDEX(@char, @result) = 0
BEGIN
SET @result = @result + @char;
END
SET @i = @i + 1;
END
RETURN @result;
END;
-- 查询去重后的结果
SELECT id, dbo.fn_remove_duplicate(content) AS new_content FROM test_str;
注意事项
- 上述方法会保留字符第一次出现的位置,后续重复的字符会被移除,如果需要保留最后一次出现的字符,可以调整判断逻辑,从字符串末尾开始遍历。
- 如果字符串中包含中文、特殊符号等多字节字符,需要确保使用的字符串函数支持多字节处理,比如MySQL里用
CHAR_LENGTH代替LENGTH计算字符数,避免拆分错误。 - 对于超长字符串,循环遍历的性能会有所下降,如果处理的数据量较大,可以评估是否需要优化逻辑,比如先拆分字符到临时表再做去重聚合。