如何解析SQL Server表单元格中存储的INI格式长文本?
用T-SQL解析INI文本为结构化表
要实现将SQL Server表中存储的INI格式文本拆分为Block, Key, Value的结构化数据,可借助以下T-SQL核心特性:
STRING_SPLIT():将多行INI文本按换行符拆分为单独行- 递归CTE:跟踪当前遍历到的INI块(Block)名称
- 字符串处理函数(
CHARINDEX()、SUBSTRING()、TRIM()、LEFT()、RIGHT()):提取块名、键名和对应值 CROSS APPLY:关联原表和拆分后的行数据
具体实现步骤与代码
假设你的原表名为INI_Source,结构为id INT, rawINI NVARCHAR(MAX),以下是完整实现代码:
- 先将
rawINI按换行符拆分为单行记录,同时保留原表的id用于关联:
-- 临时存储拆分后的每一行INI内容 DROP TABLE IF EXISTS #SplitLines; SELECT s.id, LTRIM(RTRIM(value)) AS LineContent, -- 生成行号,保证INI内容的顺序 ROW_NUMBER() OVER(PARTITION BY s.id ORDER BY (SELECT NULL)) AS LineNum INTO #SplitLines FROM INI_Source s CROSS APPLY STRING_SPLIT(s.rawINI, CHAR(13)+CHAR(10)) -- 按Windows换行符拆分 WHERE LTRIM(RTRIM(value)) <> ''; -- 过滤空行
- 用递归CTE遍历每行,跟踪当前Block并提取Key-Value:
WITH INIParser AS ( -- 锚点成员:初始化第一行的Block(如果第一行是Block) SELECT id, LineNum, -- 提取Block名称:去掉前后的[] CASE WHEN LineContent LIKE '[%]' THEN TRIM('[]' FROM LineContent) ELSE NULL END AS CurrentBlock, -- 非Block行的Key和Value CASE WHEN LineContent NOT LIKE '[%]' AND CHARINDEX('=', LineContent) > 0 THEN LEFT(LineContent, CHARINDEX('=', LineContent)-1) ELSE NULL END AS KeyName, CASE WHEN LineContent NOT LIKE '[%]' AND CHARINDEX('=', LineContent) > 0 THEN SUBSTRING(LineContent, CHARINDEX('=', LineContent)+1, LEN(LineContent)) ELSE NULL END AS KeyValue FROM #SplitLines WHERE LineNum = 1 UNION ALL -- 递归成员:逐行处理,继承上一行的Block(如果当前行不是新Block) SELECT sl.id, sl.LineNum, CASE WHEN sl.LineContent LIKE '[%]' THEN TRIM('[]' FROM sl.LineContent) ELSE ip.CurrentBlock END AS CurrentBlock, CASE WHEN sl.LineContent NOT LIKE '[%]' AND CHARINDEX('=', sl.LineContent) > 0 THEN LEFT(sl.LineContent, CHARINDEX('=', sl.LineContent)-1) ELSE NULL END AS KeyName, CASE WHEN sl.LineContent NOT LIKE '[%]' AND CHARINDEX('=', sl.LineContent) > 0 THEN SUBSTRING(sl.LineContent, CHARINDEX('=', sl.LineContent)+1, LEN(sl.LineContent)) ELSE NULL END AS KeyValue FROM #SplitLines sl JOIN INIParser ip ON sl.id = ip.id AND sl.LineNum = ip.LineNum + 1 ) -- 最终筛选出Key-Value行,整理为目标结构 SELECT CurrentBlock AS Block, KeyName AS [Key], KeyValue AS Value FROM INIParser WHERE KeyName IS NOT NULL -- 只保留Key-Value行,过滤Block行 ORDER BY id, LineNum;
关键细节说明
- 过滤空行:避免处理INI文本中的无效空行
- 行号排序:保证INI内容的顺序和原文本一致,避免Block和Key对应错误
- 边界处理:兼容
Key3=这类无值的键,此时Value字段为NULL - Block继承:递归CTE会自动将后续的Key-Value行关联到最近的Block
内容的提问来源于stack exchange,提问作者KUL
相关产品推荐
相关产品推荐

