如何拆分包含 XML 字符串的 SQL 字段
Posted
技术标签:
【中文标题】如何拆分包含 XML 字符串的 SQL 字段【英文标题】:How can i split SQL field that contains an XML string 【发布时间】:2019-10-01 11:34:06 【问题描述】:我有一个带有 XML sn-ps 的字段。我想创建一个#TempTable
,它将包含 XML 数据的拆分,但只显示两个特定标签之间的任何字符。
字段值看起来像这样(为易读而包装):
<monthdate>2019-07-01</monthdate>
<automitemno>302</automitemno>
<amount>1.190000000000</amount>
<currentamount>0.000000000000</currentamount>
<langitemno>1</langitemno>
<monthdate>2019-07-01</monthdate>
<automitemno>2131</automitemno>
<amount>0.386750000000</amount>
<currentamount>0.000000000000</currentamount>
<langitemno>1</langitemno>
等等。我希望#TempTable
中的列包含标签<monthdate>
和</amount>
之间每次出现的数据。它应该如下所示:
【问题讨论】:
您真的想要没有符号的输出 (< & >
)?还是这只是问题格式的问题?
嗨,是的,这是问题的格式,抱歉。我想要输出中的 (),因为我需要在仪表板报告的其他几个查询中使用临时表。
另外,您使用的是哪个 SQL 引擎? MS SQL Server、mysql、PostgreSQL,以及哪个版本?
MS SQL SERVER 管理工作室 17
【参考方案1】:
我不确定你指的是哪一个。第一个将它们作为单独的 xml 行返回,另一个将它们作为类型数据行返回:
DECLARE @sample TABLE
(
id INT IDENTITY,
xmlSnippet VARCHAR(MAX)
);
INSERT @sample
(
xmlSnippet
)
VALUES
('<monthdate>2019-07-01</monthdate>
<automitemno>302</automitemno>
<amount>1.190000000000</amount>
<currentamount>0.000000000000</currentamount>
<langitemno>1</langitemno>
<monthdate>2019-07-01</monthdate>
<automitemno>2131</automitemno>
<amount>0.386750000000</amount>
<currentamount>0.000000000000</currentamount>
<langitemno>1</langitemno>');
DECLARE @tempTable TABLE
(
id INT,
XMLValue XML
);
INSERT @tempTable
(
id,
XMLValue
)
SELECT id,
CAST('<monthdate>' + value AS XML)
FROM @sample
CROSS APPLY STRING_SPLIT(REPLACE(xmlSnippet, '<monthdate>', '&'), '&')
WHERE value <> '';
SELECT *
FROM @tempTable;
DECLARE @tempTable2 TABLE
(
monthDate DATE,
autoItemNo INT,
amount MONEY,
currentAmount MONEY
);
WITH myData (id, xmlRow)
AS (SELECT id,
CAST('<monthdate>' + value AS XML)
FROM @sample
CROSS APPLY STRING_SPLIT(REPLACE(xmlSnippet, '<monthdate>', '&'), '&')
WHERE value <> '')
INSERT @tempTable2
(
monthDate,
autoItemNo,
amount,
currentAmount
)
SELECT myData.xmlRow.value('/monthdate[1]', 'date'),
myData.xmlRow.value('/automitemno[1]', 'int'),
myData.xmlRow.value('/amount[1]', 'money'),
myData.xmlRow.value('/currentamount[1]', 'money')
FROM myData;
SELECT *
FROM @tempTable2;
编辑:我添加了DBFiddle demo
【讨论】:
感谢以上内容,v 有帮助,只是一个额外的说明。我将如何从表和列中调用它,即..而不是将值设置为已知的 Nvarchar 值,如果要指定值在哪个表和列中并将结果插入到临时表中怎么办? 其实我是从表中调用的,@sample 是一个表变量,可能是一个真正的持久化表。 根据 TEMPORARY TABLE,只需将表变量 (@tempTable) 替换为像 #tempTable 这样的临时表。 嘿:我查询返回:无效的对象名称'STRING_SPLIT'??有任何想法吗?它识别出粉红色的命令但出错了? String_Split 是在 2016 版(兼容级别 130)中引入的。你用的是什么版本?检查我提供链接的 db fiddle 演示。【参考方案2】:这里有一个解决方案,可以提供与所写内容完全相同的文本:
declare @xml as nvarchar(max)
set @xml = N'<monthdate>2019-07-01</monthdate>
<automitemno>302</automitemno>
<amount>1.190000000000</amount>
<currentamount>0.000000000000</currentamount>
<langitemno>1</langitemno>
<monthdate>2019-07-01</monthdate>
<automitemno>2131</automitemno>
<amount>0.386750000000</amount>
<currentamount>0.000000000000</currentamount>
<langitemno>1</langitemno>'
select replace(substring(a.value, charindex('<monthdate>',a.value)+11, charindex('</amount>', a.value)-16), char(10), '') as [XMLValue]
from string_split(replace(@xml, '</langitemno>', char(30)), char(30)) a
where a.value like '%<monthdate>%</amount>%'
DBFiddle
【讨论】:
以上是关于如何拆分包含 XML 字符串的 SQL 字段的主要内容,如果未能解决你的问题,请参考以下文章
如何避免作为 sql 查询输出的一部分返回的字符串值被拆分为 bash/shell 脚本中数组中的不同字段