2016-07-06 54 views
3

我似乎很难与XML。我正在寻找适当的身份证附加到每行XML查询附加适当的ID

Declare @User table (id int,First_Name varchar(50),Last_Name varchar(50),EMail varchar(50)) 
Insert into @User values 
(1,'John','Smith','[email protected]'), 
(2,'Jane','Doe' ,'[email protected]') 

Declare @XML xml 
Set @XML = (Select * from @User for XML RAW) 

Select ID = 1 -- < dummy need actual id 
     ,Item = cast(x.v.query('local-name(.)') as varchar(100)) 
     ,Value = x.v.value('.','varchar(150)') 
From @xml.nodes('//@*') x(v) 

我目前的结果是。

ID Item  Value 
1 id   1 
1 First_Name John 
1 Last_Name Smith 
1 EMail  [email protected] 
1 id   2 
1 First_Name Jane 
1 Last_Name Doe 
1 EMail  [email protected] 

期望结果将是。

ID Item  Value 
1 id   1 
1 First_Name John 
1 Last_Name Smith 
1 EMail  [email protected] 
2 id   2 
2 First_Name Jane 
2 Last_Name Doe 
2 EMail  [email protected] 
+0

这是一个很好的问题:Copy'n'pasteable测试场景,自己的努力,错误的产出,预期的产出和明确而简短的描述。如果更多的问题是这样的...... :-)投了票! – Shnugo

+0

Bo!我感到尴尬......谢谢! – Shnugo

+0

@Shnugo不要尴尬,我已经从你的帖子中获得了很多里程 –

回答

4

试试这样说:

顺便说一句:你是非常接近!

Declare @User table (id int,First_Name varchar(50),Last_Name varchar(50),EMail varchar(50)) 
Insert into @User values 
(1,'John','Smith','[email protected]'), 
(2,'Jane','Doe' ,'[email protected]') 

Declare @XML xml 
Set @XML = (Select * from @User for XML RAW) 

SELECT @XML; 

/* 
<row id="1" First_Name="John" Last_Name="Smith" EMail="[email protected]" /> 
<row id="2" First_Name="Jane" Last_Name="Doe" EMail="[email protected]" /> 
*/ 

第一.nodes()将与单排 的CROSS APPLY .nodes(./@*)会做所有属性基于行的搜索,并提供它们作为单个行中的所有元素row返回。

Select r.value('@id','int') AS ID 
     ,Attr.value('local-name(.)','varchar(max)') AS Item 
     ,Attr.value('.','varchar(max)') AS Value 
FROM @XML.nodes('/row') AS A(r) 
CROSS APPLY A.r.nodes('./@*') AS B(Attr) 
+0

FABULOUS!我尝试了无数种组合。非常感谢你。 –

+0

不错的工作..我无法找到行过滤器'('./@*')'任何地方..我确实发现这一点,但如果你想排除id行..'CROSS APPLY Arnodes('。/@ * [local-name(。)!=“id”]')' – JamieD77

+0

@ JamieD77,好暗示......由于* id在*期望的输出中被提及,所以我会认为它是想要的...... – Shnugo

1

刚刚遇到了这个问题。尽管已经给出了这个问题的答案,但是想到用不同的方法来回答它,而不使用xquery。

可以使用CROSS APPLYTable Value Constructor这样实现同样的结果 -

Declare @User table (id int,First_Name varchar(50),Last_Name varchar(50),EMail varchar(50)) 
Insert into @User values 
(1,'John','Smith','[email protected]'), 
(2,'Jane','Doe' ,'[email protected]') 

SELECT r.ID, t.* FROM @User r 
CROSS APPLY (
    VALUES ('ID', cast(id as varchar)), 
      ('First_Name', First_Name), 
      ('Last_Name', Last_Name), 
      ('EMail', EMail) 
) t(Item, Value) 

结果

ID Item  Value 
--------------------- 
1 ID   1 
1 First_Name John 
1 Last_Name Smith 
1 EMail  [email protected] 
2 ID   2 
2 First_Name Jane 
2 Last_Name Doe 
2 EMail  [email protected] 
+0

欣赏答案,我是这种技术的忠实粉丝,但对于原始问题,我正在寻找一种动态方法+1 –