首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

SQL Server 字串分割函數實現:自定義函數 getstrcount、getstrofindex、getEPnum 完整代碼

     編輯:MySQL 資料庫相關知識

適用環境

本文代碼為 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;

MySQL 8.0+ 現代替代方案

-- 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;

效能對比

最佳實踐建議

  1. 避免在 SQL 中分割字串:應用層處理後傳入臨時表/表值參數
  2. 必須在 SQL 中:優先用 JSON_TABLE 或 遞歸 CTE
  3. 舊版本:考慮 CLR 函數 或 Numbers/Tally 表聯結
  4. 分隔符固定為單字符時,SUBSTRING_INDEX 技巧效能較好
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
方案適用版本效能維護性
自定義標量函數所有極差(逐行調用)低
表值函數 (TVF)2008+中等中
遞歸 CTE8.0+ / SQL Server 2008+好高
JSON_TABLEMySQL 8.0.4+優高
應用層分割所有最佳最高