There is a table:
CREATE TABLE temp
(ID int, name varchar(50));
INSERT INTO temp
([ID], [name])
VALUES
(1, 'Value 1'),
(2, 'Value 2');
Need SQL query returning the following result:
<root>
<row>
<param name="first">1</param>
<param name="second">Value 1</param>
</row>
<row>
<param name="first">2</param>
<param name="second">Value 2</param>
</row>
</root>
Estimated Query is:
SELECT
[ID] as [param/@name['first']],
[name] as [param/@name['second']]
FROM
temp
for xml path('row'), root('root')
Please correct Query to make it work.
XQuery FLWOR expression gives you a full control on the shape of the XML. Check it out:
SQL
-- DDL and sample data population, start
DECLARE @tbl TABLE (id INT PRIMARY KEY, [name] varchar(50));
INSERT INTO @tbl (id, [name])
VALUES (1, 'Value 1')
, (2, 'Value 2');
-- DDL and sample data population, end
;WITH rs(xml_data) AS
(
SELECT *
FROM @tbl
FOR XML PATH('row'), TYPE, ROOT('root')
)
SELECT xml_data.query('<root>
{
for $r in /root/row
return
<row>
<param name="first">{data($r/id/text())}</param>
<param name="second">{data($r/name/text())}</param>
</row>
}
</root>') AS xml_output
FROM rs;
Output
<root>
<row>
<param name="first">1</param>
<param name="second">Value 1</param>
</row>
<row>
<param name="first">2</param>
<param name="second">Value 2</param>
</row>
</root>
The simplest approach might be this:
SELECT 'first' as [param/@name]
,ID as [param]
,''
,'second' as [param/@name]
,[name] as [param]
FROM temp t
FOR XML PATH('row'), root('root');
The idea in short:
The engine works down the columns and finds
<root>
<row>
for each row of the set<param>
, we have to open it.@name
.ID
) is also living in <param>
, which is still open. Add it as a text()
node.<param>
... Okay, the next column looks better. There is an element <param>
... Okay, the last one is closed, we have to open a new one!
and so on...
This also works with fragments of paths:
SELECT 'first' as [param/onemore/@name]
,ID as [param/onemore]
,'' AS [param]
,'second' as [param/onemore/@name]
,[name] as [param/onemore]
FROM temp t
FOR XML PATH('row'), root('root');
The result
<root>
<row>
<param>
<onemore name="first">1</onemore>
<onemore name="second">Value 1</onemore>
</param>
</row>
<row>
<param>
<onemore name="first">2</onemore>
<onemore name="second">Value 2</onemore>
</param>
</row>
</root>
In this case we re-open <onemore>
, but we stay within the open <param>
.
You can achieve this with sub-queries:
SELECT 'first' as [param/@name],
ID as [param],
(SELECT 'second' as [param/@name],
name as [param]
FROM temp t1 WHERE t1.ID = t.ID
FOR XML PATH(''), TYPE )
FROM temp t
FOR XML PATH('row'), root('root')
Output:
<root>
<row>
<param name="first">1</param>
<param name="second">Value 1</param>
</row>
<row>
<param name="first">2</param>
<param name="second">Value 2</param>
</row>
</root>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.