原文給出的是 T-SQL 語法(RETURNS @t TABLE),MySQL 不支持返回表的函數。MySQL 8.0+ 可用 JSON_TABLE 或 CTE 替代。
CREATE FUNCTION `Get_StrArrayLength`(str VARCHAR(1024), split VARCHAR(10))
RETURNS INT
DETERMINISTIC
BEGIN
DECLARE len INT DEFAULT 1;
DECLARE pos INT;
SET str = TRIM(str);
SET pos = LOCATE(split, str);
WHILE pos > 0 DO
SET len = len + 1;
SET pos = LOCATE(split, str, pos + CHAR_LENGTH(split));
END WHILE;
RETURN len;
END;
用法:SELECT Get_StrArrayLength('78,1,2,3', ','); -- 返回 4
CREATE FUNCTION `Get_StrArrayStrOfIndex`(str VARCHAR(1024), split VARCHAR(10), idx INT)
RETURNS VARCHAR(1024)
DETERMINISTIC
BEGIN
DECLARE start_pos INT DEFAULT 1;
DECLARE delim_len INT DEFAULT CHAR_LENGTH(split);
DECLARE cur_idx INT DEFAULT 1;
DECLARE pos INT;
SET str = TRIM(str);
SET pos = LOCATE(split, str);
WHILE pos > 0 AND cur_idx < idx DO
SET start_pos = pos + delim_len;
SET pos = LOCATE(split, str, start_pos);
SET cur_idx = cur_idx + 1;
END WHILE;
IF pos = 0 THEN SET pos = CHAR_LENGTH(str) + 1; END IF;
RETURN SUBSTRING(str, start_pos, pos - start_pos);
END;
用法:SELECT Get_StrArrayStrOfIndex('8,9,4', ',', 2); -- 返回 '9'
WITH RECURSIVE split_cte AS (
SELECT
1 AS idx,
TRIM(SUBSTRING_INDEX('a,b,c,d', ',', 1)) AS val,
SUBSTRING('a,b,c,d', CHAR_LENGTH(SUBSTRING_INDEX('a,b,c,d', ',', 1)) + 2) AS rest
UNION ALL
SELECT
idx + 1,
TRIM(SUBSTRING_INDEX(rest, ',', 1)),
SUBSTRING(rest, CHAR_LENGTH(SUBSTRING_INDEX(rest, ',', 1)) + 2)
FROM split_cte
WHERE rest != ''
)
SELECT idx, val FROM split_cte;
SELECT jt.idx, jt.val
FROM JSON_TABLE(
CONCAT('["', REPLACE('a,b,c,d', ',', '","'), '"]'),
"$[*]" COLUMNS (
idx FOR ORDINALITY,
val VARCHAR(100) PATH "$"
)
) AS jt;
| 方案 | 版本要求 | 性能 | 適用場景 |
|---|---|---|---|
| 自定義函數 | 5.0+ | 中(函數調用開銷) | 舊版本、簡單分割 |
| CTE 遞歸 | 8.0+ | 高(集合操作) | 複雜 ETL、報表 |
| JSON_TABLE | 8.0.4+ | 最高(原生優化) | 大數據量、結構化輸出 |
| 應用層分割 | 任意 | 最好 | 高頻、高併發業務 |
WHERE/JOIN 中調用分割函數 → 全表掃描SUBSTRING_INDEX 組合技巧