首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

SQL Server 2008 使用 CTE 將字串分割轉換為資料表

     編輯:關於SqlServer

需求場景

應用層傳入逗點分隔的 ID 字串(如 '1,2,4,8'),存儲過程內需轉換為資料表值參數進行 IN 查詢或 JOIN 操作。SQL Server 2008 引入的 遞迴 CTE(Common Table Expression) 完美解決此問題,無需迴圈或 CLR。

核心函數實作:strToTable

CREATE FUNCTION [dbo].[strToTable] (
    @array VARCHAR(MAX),
    @del CHAR(1)
)
RETURNS @listTable TABLE (item INT)
AS
BEGIN
    WITH rep (item, list) AS (
        -- 錨點:取第一個分隔符前的子字串
        SELECT 
            SUBSTRING(@array, 1, CHARINDEX(@del, @array, 1) - 1) AS item,
            SUBSTRING(@array, CHARINDEX(@del, @array, 1) + 1, LEN(@array)) + @del AS list
        UNION ALL
        -- 遞迴:逐個取出後續項目
        SELECT 
            SUBSTRING(list, 1, CHARINDEX(@del, list, 1) - 1) AS item,
            SUBSTRING(list, CHARINDEX(@del, list, 1) + 1, LEN(list)) AS list
        FROM rep
        WHERE LEN(rep.list) > 0
    )
    INSERT INTO @listTable
    SELECT item FROM rep
    OPTION (MAXRECURSION 0);  -- 允許超過 100 級遞迴
    RETURN;
END
GO

呼叫範例

DECLARE @array VARCHAR(MAX) = '1,2,4,8';
SELECT item FROM dbo.strToTable(@array, ',');
-- 結果:
-- item
-- ----
-- 1
-- 2
-- 4
-- 8

關鍵技術解析

技術點說明
遞迴 CTEWITH ... AS (anchor UNION ALL recursive) 結構,錨點執行一次,遞迴部份重複執行直到終止條件
CHARINDEX 定位分隔符位置配合 SUBSTRING 切割字串
尾部加分隔符+ @del 確保最後一個項目也能被 CHARINDEX 找到
OPTION (MAXRECURSION 0)移除預設 100 級遞迴限制,支援超長字串分割
回傳表值函數RETURNS @table TABLE 直接可在 FROM 子句使用

進階變體:支援字串型別項目

CREATE FUNCTION [dbo].[strToTableStr] (
    @array NVARCHAR(MAX),
    @del NCHAR(1)
)
RETURNS @listTable TABLE (item NVARCHAR(4000))
AS
BEGIN
    WITH rep (item, list) AS (
        SELECT 
            SUBSTRING(@array, 1, CHARINDEX(@del, @array, 1) - 1),
            SUBSTRING(@array, CHARINDEX(@del, @array, 1) + 1, LEN(@array)) + @del
        UNION ALL
        SELECT 
            SUBSTRING(list, 1, CHARINDEX(@del, list, 1) - 1),
            SUBSTRING(list, CHARINDEX(@del, list, 1) + 1, LEN(list))
        FROM rep
        WHERE LEN(rep.list) > 0
    )
    INSERT INTO @listTable SELECT item FROM rep OPTION (MAXRECURSION 0);
    RETURN;
END
GO

-- 使用範例
SELECT item FROM dbo.strToTableStr(N'苹果,香蕉,橘子', N',');

效能與替代方案比較

方案適用版本效能維護性備註
遞迴 CTE 函數SQL 2008+中等(萬筆內佳)高純 T-SQL,無外部依賴
STRING_SPLITSQL 2016+高(原生優化)最高不保證順序,無索引值
OPENJSONSQL 2016+高高需 JSON 格式 ['1','2']
XML 解析SQL 2005+低低舊版相容方案
CLR 函數SQL 2005+最高中需啟用 CLR、部署組件

最佳實務建議

  1. SQL 2016+ 專案直接使用 STRING_SPLIT 或 OPENJSON
  2. SQL 2008/2012/2014 使用本文 CTE 方案,並加入 OPTION (MAXRECURSION 0)
  3. 大量資料(>10萬項)建議改用資料表值參數(TVP)由應用層直接傳遞結構化資料
  4. 函數加入 SCHEMABINDING 提升計畫快取重用率
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved