函數定義
DELIMITER $$
DROP FUNCTION IF EXISTS `radius`.`fun_split`$$
CREATE DEFINER=`root`@`%` FUNCTION `fun_split`(nm VARCHAR(100))
RETURNS VARCHAR(500) CHARSET latin1
READS SQL DATA
BEGIN
DECLARE i INT DEFAULT 1;
DECLARE rtn INT;
DECLARE rtn1 INT;
DECLARE sec VARCHAR(10);
DECLARE rtnstr VARCHAR(500) DEFAULT '';
DECLARE len INT DEFAULT LENGTH(nm);
WHILE i <= len DO
SET rtn = ASCII(SUBSTRING(nm, i, 1));
IF rtn > 127 THEN
-- 雙字節字符(中文 GBK 編碼範圍)
SET rtn1 = ASCII(SUBSTRING(nm, i, 2));
IF rtn1 > 127 THEN
-- 進一步檢測後續字節判斷是否為 4 字節序列
IF i < len - 1 AND ASCII(SUBSTRING(nm, i, 3)) > 127 AND ASCII(SUBSTRING(nm, i, 4)) > 127 THEN
SET sec = CONCAT(
RIGHT(CONCAT('00', rtn - 160), 2),
RIGHT(CONCAT('00', rtn1 - 160), 2),
RIGHT(CONCAT('00', ASCII(SUBSTRING(nm, i, 3)) - 160), 2),
RIGHT(CONCAT('00', ASCII(SUBSTRING(nm, i, 4)) - 160), 2),
' '
);
ELSE
SET sec = '';
END IF;
ELSE
SET sec = CONCAT(CHAR(rtn), CHAR(rtn1));
END IF;
SET i = i + 1;
ELSE
-- 單字節字符(ASCII)
IF i < len - 1 AND ASCII(SUBSTRING(nm, i, 2)) > 127 AND ASCII(SUBSTRING(nm, i, 3)) > 127 THEN
SET sec = CONCAT(CHAR(rtn), ' ');
ELSE
SET sec = CHAR(rtn);
END IF;
END IF;
SET rtnstr = CONCAT(rtnstr, sec);
SET i = i + 1;
END WHILE;
RETURN rtnstr;
END$$
DELIMITER ;
算法邏輯解析
- 遍歷輸入字符串每個位置
i。
ASCII > 127 判定為多字節字符(GBK 中文雙字節,首字節 0x81-0xFE)。
- 雙字節情況:讀取次字節,雙雙 >127 視為漢字,按
字節-160 轉兩位十六進制編碼拼接。
- 檢測 4 字節序列(罕見擴展),同理轉碼並加空格分隔。
- 單字節情況:若後續兩字節均 >127(疑似中文開頭),輸出字符+空格;否則直接輸出字符。
- 結果以空格分隔各編碼單元,返回 VARCHAR(500)。
適用場景與局限
- 適用:GBK 編碼環境下中英文混合串簡易分詞/轉碼展示。
- 局限:
- 硬編碼 GBK 邏輯,不支持 UTF-8(多字節判斷邏輯完全不同)。
- 不支持大小寫敏感處理(未區分)。
- 不支持標點符號、數字等非字母字符的語義分詞。
- 性能:逐字符循環,長字符串效率低,不適合大數據量 SQL 中調用。
現代替代方案
- 應用層分詞:jieba (Python)、IK Analyzer (Java)、gojieba (Go)。
- MySQL 8.0+ 原生全文解析器插件接口(需 C++ 開發)。
- 存儲過程中避免複雜字符串處理,交給應用層完成。