本文代碼為 SQL Server (T-SQL) 語法,非 MySQL。MySQL 8.0+ 可用 JSON_TABLE / 遞歸 CTE 分割字串。
-- 1. 計算分割後元素個數
CREATE FUNCTION dbo.getstrcount (@str VARCHAR(8000), @splitstr VARCHAR(100))
RETURNS INT
AS
BEGIN
DECLARE @count INT = 0, @start INT = 1, @loc INT;
IF LEN(@str) = 0 OR CHARINDEX(@splitstr, @str) = 0 RETURN 0;
WHILE @start <= LEN(@str) BEGIN
SET @loc = CHARINDEX(@splitstr, @str, @start);
IF @loc = 0 SET @loc = LEN(@str) + 1;
SET @count = @count + 1;
SET @start = @loc + LEN(@splitstr);
END
RETURN @count;
END;
-- 2. 取得指定索引位置的子字串(1-based)
CREATE FUNCTION dbo.getstrofindex (@str VARCHAR(8000), @splitstr VARCHAR(4), @index INT)
RETURNS VARCHAR(8000)
AS
BEGIN
DECLARE @start INT = 1, @loc INT, @i INT = 1;
WHILE @i < @index AND @start <= LEN(@str) BEGIN
SET @loc = CHARINDEX(@splitstr, @str, @start);
IF @loc = 0 SET @loc = LEN(@str) + 1;
SET @start = @loc + LEN(@splitstr);
SET @i = @i + 1;
END
IF @start > LEN(@str) RETURN '';
SET @loc = CHARINDEX(@splitstr, @str, @start);
IF @loc = 0 SET @loc = LEN(@str) + 1;
RETURN SUBSTRING(@str, @start, @loc - @start);
END;
-- 3. 業務函數:從逗號分隔 epnum 列表中找第一個在線用戶
CREATE FUNCTION dbo.getEPnum (@str VARCHAR(8000))
RETURNS VARCHAR(8000)
AS
BEGIN
DECLARE @result VARCHAR(8000) = '00000000', @cnt INT, @i INT = 1, @epnum VARCHAR(50), @online BIT;
IF LEN(@str) = 0 RETURN @result;
SET @cnt = dbo.getstrcount(@str, ',');
WHILE @i <= @cnt BEGIN
SET @epnum = dbo.getstrofindex(@str, ',', @i);
SELECT @online = online FROM wwchat_user WHERE epnum = @epnum;
IF @online = 1 BEGIN
SET @result = @epnum;
BREAK;
END
SET @i = @i + 1;
END
RETURN @result;
END;
-- 1. 遞歸 CTE 分割
WITH RECURSIVE split AS (
SELECT 1 AS idx,
SUBSTRING_INDEX(SUBSTRING_INDEX(str, ',', 1), ',', -1) AS val,
str
UNION ALL
SELECT idx + 1,
SUBSTRING_INDEX(SUBSTRING_INDEX(str, ',', idx + 1), ',', -1),
str
FROM split WHERE idx < 100 -- 防無限遞歸
)
SELECT * FROM split WHERE val != '';
-- 2. JSON_TABLE (8.0.4+)
SELECT jt.val FROM JSON_TABLE(CONCAT('["', REPLACE(str, ',', '","'), '"]'), '$[*]' COLUMNS (val VARCHAR(100) PATH '$')) jt;
-- 3. 尋找第一個在線(假設有 users 表)
SELECT u.epnum FROM users u
JOIN (SELECT TRIM(val) AS epnum FROM JSON_TABLE(...) jt) t ON u.epnum = t.epnum
WHERE u.online = 1 LIMIT 1;
| 方案 | 適用版本 | 效能 | 維護性 |
|---|---|---|---|
| 自定義標量函數 | 所有 | 極差(逐行調用) | 低 |
| 表值函數 (TVF) | 2008+ | 中等 | 中 |
| 遞歸 CTE | 8.0+ / SQL Server 2008+ | 好 | 高 |
| JSON_TABLE | MySQL 8.0.4+ | 優 | 高 |
| 應用層分割 | 所有 | 最佳 | 最高 |