提供一個可直接部署的 SerializeJSON 預存程序,接受任意 SELECT 陳述式字串,透過 FOR XML RAW 產生中繼 XML,再以 T-SQL 字串剖析轉換為 JSON 陣列格式,適用於 SQL Server 2016 前無原生 FOR JSON 的環境。
SET ANSI_NULLS ON; GO
SET QUOTED_IDENTIFIER ON; GO
CREATE PROCEDURE [dbo].[SerializeJSON]
@ParameterSQL AS VARCHAR(MAX)
AS
BEGIN
DECLARE @SQL NVARCHAR(MAX), @XMLString VARCHAR(MAX), @XML XML, @ParamList NVARCHAR(1000) = N'@XML XML OUTPUT';
-- 1. 動態 SQL 執行查詢並取得 XML 結果
SET @SQL = N'WITH PrepareTable (XMLString) AS (' + @ParameterSQL + N' FOR XML RAW, TYPE, ELEMENTS) SELECT @XML = [XMLString] FROM [PrepareTable]';
EXEC sp_executesql @SQL, @ParamList, @XML = @XML OUTPUT;
SET @XMLString = CAST(@XML AS VARCHAR(MAX));
-- 2. 字串剖析 XML 轉 JSON
DECLARE @JSON VARCHAR(MAX) = '', @Row VARCHAR(MAX);
DECLARE @RowStart INT, @RowEnd INT, @FieldStart INT, @FieldEnd INT;
DECLARE @Key VARCHAR(MAX), @Value VARCHAR(MAX);
DECLARE @StartRoot VARCHAR(100) = '', @EndRoot VARCHAR(100) = '
';
DECLARE @StartField VARCHAR(100) = '<', @EndField VARCHAR(100) = '>';
SET @RowStart = CHARINDEX(@StartRoot, @XMLString, 0);
WHILE @RowStart > 0 BEGIN
SET @RowStart += LEN(@StartRoot);
SET @RowEnd = CHARINDEX(@EndRoot, @XMLString, @RowStart);
SET @Row = SUBSTRING(@XMLString, @RowStart, @RowEnd - @RowStart);
SET @JSON += '{';
SET @FieldStart = CHARINDEX(@StartField, @Row, 0);
WHILE @FieldStart > 0 BEGIN
SET @FieldStart += LEN(@StartField);
SET @FieldEnd = CHARINDEX(@EndField, @Row, @FieldStart);
SET @Key = SUBSTRING(@Row, @FieldStart, @FieldEnd - @FieldStart);
SET @JSON += '"' + @Key + '":';
SET @FieldStart = @FieldEnd + 1;
SET @FieldEnd = CHARINDEX('', @Row, @FieldStart);
SET @Value = SUBSTRING(@Row, @FieldStart, @FieldEnd - @FieldStart);
SET @JSON += '"' + @Value + '",';
SET @FieldStart = CHARINDEX(@StartField, @Row, @FieldEnd);
END
IF LEN(@JSON) > 0 SET @JSON = SUBSTRING(@JSON, 1, LEN(@JSON) - 1); -- 移除尾端逗號
SET @JSON += '},';
SET @RowStart = CHARINDEX(@StartRoot, @XMLString, @RowEnd);
END
IF LEN(@JSON) > 0 SET @JSON = SUBSTRING(@JSON, 1, LEN(@JSON) - 1); -- 移除尾端逗號
SET @JSON = '[' + @JSON + ']';
SELECT @JSON;
END; GO
EXEC [SerializeJSON] 'SELECT * FROM [Employee_TBL]';
輸出格式:[{"col1":"val1","col2":"val2"},{"col1":"val3","col2":"val4"}]
"、\、控制字元會產生無效 JSON,需自行增補 REPLACE 跳脫邏輯。FOR XML ELEMENTS 預設略過 NULL 欄位,導致 Key 缺失;建議查詢端用 ISNULL(col, '') 或 ELEMENTS XSINIL。@ParameterSQL 直接拼接,呼叫端必須確保輸入安全(內部工具可接受,對外服務嚴禁)。-- 原生 FOR JSON,效能優、型別保留、標準跳脫
SELECT * FROM Employee_TBL FOR JSON PATH, ROOT('Data');
-- 指定根名稱、輸出陣列
SELECT * FROM Employee_TBL FOR JSON AUTO;
**強烈建議**:支援版本請直接使用 FOR JSON,僅在舊版本維護專案時使用本預存程序。