Sql server 从XML列中选择所有XML节点
我有一个带有XML列的表。每个条目的XML结构都是完全平坦的,甚至没有父标记-这是一个条目的示例:Sql server 从XML列中选择所有XML节点,sql-server,xml,tsql,xquery,sql-server-2016,Sql Server,Xml,Tsql,Xquery,Sql Server 2016,我有一个带有XML列的表。每个条目的XML结构都是完全平坦的,甚至没有父标记-这是一个条目的示例: <tag1>1.22</tag1> <tag3>5</tag3> <tag12>-1.22</tag> 然后在我这端解析XML。或者我显然可以编写xpath查询来选择列中的标记,这就是我想要的,除了有大约1000个可能的标记名,我不想把它们全部写出来,可能会遗漏一个 简言之,我该如何着手: | ID | XML type c
<tag1>1.22</tag1>
<tag3>5</tag3>
<tag12>-1.22</tag>
然后在我这端解析XML。或者我显然可以编写xpath查询来选择列中的标记,这就是我想要的,除了有大约1000个可能的标记名,我不想把它们全部写出来,可能会遗漏一个
简言之,我该如何着手:
| ID | XML type column |
| 1 | <tag1>1</tag1><tag2>2</tag2> |
| 2 | <tag2>8</tag2><tag34>1</tag34> |
对于我在数据集中可以找到的任何标记,而不事先知道它们?我也会满足于此:
| ID | tag | value |
| 1 | tag1 | 1 |
| 1 | tag2 | 2 |
| 2 | tag2 | 8 |
| 2 | tag34 | 1 |
在MS SQL Server中,使用XML数据类型方法和XQuery相对简单。SQL Server可以在没有根元素的情况下处理XML片段,而不会出现任何问题 您试图实现的是XML分解。尽管您需要知道1个XML元素名或2个XML元素名的顺序位置 查看方法1 SQL
以下内容将把没有根节点的平面XML转换为经典的EAV列表:
DECLARE @tbl TABLE(ID INT IDENTITY, YourXml XML);
INSERT INTO @tbl VALUES
('<tag1>1</tag1><tag2>2</tag2>')
,('<tag3>3</tag3><tag4>4</tag4><tag5>5</tag5>');
XQuery函数local name允许查询元数据,文本节点表示元素的内容 我也会使用一个长的表示法,比如:|ID | tag | value | 1 | tag1 | 1 | tag2 | 2 | tag2 | 8 | 2 | tag34 | 1 |您的答案与MSSQL本身非常相似,运行正常,但是否有更具伸缩性的方法?在我的例子中,我甚至没有预先准备好所有的标签名,即使我有,它的标签数也超过1000个。我知道如何生成和计算SQL字符串,但这似乎更像是一种黑客行为,而不是一种解决方案,尤其是在SQL中操作字符串。长表单表格的解决方案也足够了。请提供更多关于计划如何使用…>1000个标记的详细信息…?行是表单,标记是字段。有超过30种不同类型的表单,它们的字段有时会重叠,但没有一种表单类型具有所有字段,因此,为了获得所有有效的字段名,如果要使用Xquery,我必须以某种手动方式手动解析未指定数量的记录。当然,这应该有规范,但我离数据源非常远,我不想在更新规范的情况下遗漏条目。那么@Shnugo将数据作为键/值对检索的想法呢?我的朋友,你是一个向导,这尤其棒,因为我使用的是这种格式的数据anyway@LiudvikasAkelis,很高兴听到建议的解决方案对您有效。
| ID | tag | value |
| 1 | tag1 | 1 |
| 1 | tag2 | 2 |
| 2 | tag2 | 8 |
| 2 | tag34 | 1 |
-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, xmldata XML);
INSERT INTO @tbl (xmldata) VALUES
(N'<tag1>1</tag1><tag2>2</tag2>')
,(N'<tag2>8</tag2><tag34>1</tag34>');
-- DDL and sample data population, end
-- Shred XML and convert it into a rectangular format
SELECT ID
, col.value('(tag1/text())[1]','VARCHAR(10)') AS tag1
, col.value('(tag2/text())[1]','VARCHAR(10)') AS tag2
, col.value('(tag3/text())[1]','VARCHAR(10)') AS tag3
, col.value('(tag34/text())[1]','VARCHAR(10)') AS tag34
FROM @tbl AS tbl
CROSS APPLY tbl.xmldata.nodes('.') AS tab(col);
+----+------+------+------+-------+
| ID | tag1 | tag2 | tag3 | tag34 |
+----+------+------+------+-------+
| 1 | 1 | 2 | NULL | NULL |
| 2 | NULL | 8 | NULL | 1 |
+----+------+------+------+-------+
DECLARE @tbl TABLE(ID INT IDENTITY, YourXml XML);
INSERT INTO @tbl VALUES
('<tag1>1</tag1><tag2>2</tag2>')
,('<tag3>3</tag3><tag4>4</tag4><tag5>5</tag5>');
SELECT t.ID
,AllNodes.value('local-name(.)','nvarchar(max)') AS TagName
,AllNodes.value('text()[1]','nvarchar(max)') AS TagValue
FROM @tbl t
CROSS APPLY t.YourXml.nodes('/*') A(AllNodes);