TSQL XML - Node attributes as columns or rows in same query - tsql
I'm working with an XML file with a node similar to this:
<Process>
<Step No="1" Types="D" Temp="25" Secs="6" Macro="2">Enable Mixers</Step>
<Step No="11" Types="D1" Temp="11" Secs="61" Macro="21">Enable Mixers1</Step>
<Step No="2" Types="D2" Temp="22" Secs="62" Macro="23">Enable Mixers3</Step>
</Process>
DDL:
DROP TABLE IF EXISTS MyXML2
GO
CREATE TABLE MyXML2(ID INT IDENTITY(1,1), c XML)
INSERT MyXML2(c) VALUES
('<Process><Step No="1" Types="D1" Temp="11" Secs="61" Macro="21">Enable Mixers1</Step>
<Step No="11" Types="D1" Temp="11" Secs="61" Macro="21">Enable Mixers1</Step>
<Step No="2" Types="D2" Temp="22" Secs="62" Macro="23">Enable Mixers3</Step></Process>')
GO
I need to get a database structure like this (example given for only 1 "Step" above):
StepNumber
ColumnName
ColumnValue
1
Types
D
1
Temp
25
1
Secs
6
1
Macro
2
My work so far: I've been able to map each attribute into a row.(Edit: updated to working example based on DDL above)
SELECT
col.value('local-name(.)', 'VARCHAR(50)') AS ColumnName,
col.value('.[1]', 'VARCHAR(MAX)') AS ColumnValue
FROM [MyXML2]
CROSS APPLY [c].nodes('/Process/Step/#*') doc(col)
The output looks like:
But I need the "No" attribute to be a column. Is there a way to do this all in one query?
Fiddle: http://sqlfiddle.com/#!18/e56828/9
Since originally you did not provided DDL+DML, I am presents two samples. One for table which has identification column (ID in my sample) and one without (which mean that I need to add one dynamically using ROW_NUMBER)
Demo one: When we have identification column
-- DDL+DML : this is something that the OP should provide!!!
DROP TABLE IF EXISTS MyXML2
GO
CREATE TABLE MyXML2(ID INT IDENTITY(1,1), c XML)
INSERT MyXML2(c) VALUES
('<Step No="1" Types="D1" Temp="11" Secs="61" Macro="21">Enable Mixers1</Step>'),
('<Step No="11" Types="D1" Temp="11" Secs="61" Macro="21">Enable Mixers1</Step>'),
('<Step No="2" Types="D2" Temp="22" Secs="62" Macro="23">Enable Mixers3</Step>')
GO
-- Solution
;With MyCTE as (
SELECT
MyXML2.ID,
doc.Col.value('local-name(.[1])','VARCHAR(100)') ColumnName,
doc.Col.value('.[1]','VARCHAR(100)') ColumnValue
FROM MyXML2
CROSS APPLY MyXML2.c.nodes('/Step/#*') doc(Col)
)
select
StepNumber = (SELECT MyIn.ColumnValue from MyCTE as MyIn where MyIn.ColumnName = 'No' and MyIn.ID = MyCTE.ID)
,ColumnName,ColumnValue
from MyCTE
WHERE not ColumnName = 'No'
GO
Demo two: When we do not have identification column(s)
-- DDL+DML : this is something that the OP should provide!!!
DROP TABLE IF EXISTS MyXML
GO
CREATE TABLE MyXML(c XML)
INSERT MyXML(c) VALUES
('<Step No="1" Types="D1" Temp="11" Secs="61" Macro="21">Enable Mixers1</Step>'),
('<Step No="11" Types="D1" Temp="11" Secs="61" Macro="21">Enable Mixers1</Step>'),
('<Step No="2" Types="D2" Temp="22" Secs="62" Macro="23">Enable Mixers3</Step>')
GO
-- Solution
;With MyCTE1 AS (SELECT RN = ROW_NUMBER() OVER (ORDER BY (SELECT NULL)), c FROM MyXML)
, MyCTE2 as (
SELECT
MyCTE1.RN,
doc.Col.value('local-name(.[1])','VARCHAR(100)') ColumnName,
doc.Col.value('.[1]','VARCHAR(100)') ColumnValue
FROM MyCTE1
CROSS APPLY MyCTE1.c.nodes('/Step/#*') doc(Col)
)
select
StepNumber = (SELECT MyIn.ColumnValue from MyCTE2 as MyIn where MyIn.ColumnName = 'No' and MyIn.RN = MyCTE2.RN)
,ColumnName,ColumnValue
from MyCTE2
WHERE not ColumnName = 'No'
GO
Result as expected:
Update: 2021-12-06
Following the new information which we got, here are some new solutions and explanation. The above should be useful for future readers which have similar question.
So, in the above solutions I focused on a case where we have single Step node in each row in the table. According the new information we might have multiples nodes of Step in the same value. Moreover, the Step nodes are wrapped in another node name Process
For example, a specific XML value can be: <Process><Step No="1" Types="D1" Temp="1" Secs="61" Macro="21">Enable Mixers1</Step> <Step No="11" Types="D11" Temp="11" Secs="611" Macro="21">Enable Mixers2</Step> <Step No="111" Types="D111" Temp="111" Secs="6111" Macro="23">Enable Mixers3</Step></Process>
Demo three: using variable, Step nodes structure is unknown, multiple Step nodes
In this demo I will resent solution based on the same approach as solution one
declare #xml XML = '<Process><Step No="1" Types="D1" Temp="11" Secs="61" Macro="21">Enable Mixers1</Step>
<Step No="11" Types="D1" Temp="11" Secs="61" Macro="21">Enable Mixers2</Step>
<Step No="2" Types="D2" Temp="22" Secs="62" Macro="23">Enable Mixers3</Step></Process>'
-->>> HIGHLY recommended to un-comment below lines and check what I am using as input for the CTE in this solution
--SELECT
-- t.c.value('./#No', 'VARCHAR(128)') as StepNumber,
-- t.c.query ('.') as Types
--from #xml.nodes('Process/.[1]/*')as t(c)
;With MyCTE01 as (
SELECT
t.c.value('./#No', 'INT') as StepNumber,
t.c.query ('.') as MyXML
from #xml.nodes('Process/.[1]/*')as t(c)
)
SELECT
MyCTE01.StepNumber,
doc.Col.value('local-name(.[1])','VARCHAR(100)') ColumnName,
doc.Col.value('.[1]','VARCHAR(100)') ColumnValue
FROM MyCTE01
CROSS APPLY MyCTE01.MyXML.nodes('/Step/#*') doc(Col)
WHERE not doc.Col.value('local-name(.[1])','VARCHAR(100)') = 'No'
GO
This solution will work for you but if the structure of the Step node is always the same - meaning you have the same attributes as in al the examples during the discussion, then we can get much much better solutions...
Demo four: Using variable, Step nodes has a known structure, multiple Step nodes
Since we know which attribute we have then we can hard coded use the names. In this case we do not this part which meant to find all the attributes CROSS APPLY MyCTE01.MyXML.nodes('/Step/#*')
We can use totally different approach, directly getting the values of the know attributes and using UNPIVOT. This solution provide much better performance but it is less flexible then solutions three.
declare #xml XML = '<Process><Step No="1" Types="D1" Temp="11" Secs="61" Macro="21">Enable Mixers1</Step>
<Step No="11" Types="D1" Temp="11" Secs="61" Macro="21">Enable Mixers2</Step>
<Step No="2" Types="D2" Temp="22" Secs="62" Macro="23">Enable Mixers3</Step></Process>'
--select
-- t.c.value('./#No', 'VARCHAR(128)') as id,
-- t.c.value('./#Types', 'VARCHAR(128)') as Types,
-- t.c.value('./#Temp', 'VARCHAR(128)') as Temp,
-- t.c.value('./#Secs', 'VARCHAR(128)') as Secs,
-- t.c.value('./#Macro', 'VARCHAR(128)') as Macro,
-- t.c.value('./#Macro', 'VARCHAR(128)') as Macro
--from #xml.nodes('Process/.[1]/*')as t(c)
SELECT StepNumber, Column_Name, Column_Value
FROM(
select
t.c.value('./#No', 'VARCHAR(128)') as StepNumber,
t.c.value('./#Types', 'VARCHAR(128)') as Types,
t.c.value('./#Temp', 'VARCHAR(128)') as Temp,
t.c.value('./#Secs', 'VARCHAR(128)') as Secs,
t.c.value('./#Macro', 'VARCHAR(128)') as Macro
from #xml.nodes('Process/.[1]/*')as t(c)
) p
UNPIVOT
(Column_Value FOR Column_Name IN (Types, Temp, Secs, Macro) )AS unpvt;
GO
Note! You can use this approach for unknown structure as well if you use dynamic queries and first find the attributes in the XML.
Demo five: Using variable, Step nodes has a known structure, multiple Step nodes
This solution has the same limitation as solution four (known structure) but in addition it only fits when we are working on single value like a variable. Therefore, if we want to implement it on table then we might need to loop all rows which might reduce performance dramatically. But when this solution fits the needs then it should provide best performance!
/***BEST SOLUTION - if fits the needs***/
-- XML to Tabular using OPENXML
DECLARE #idoc INT, #xml XML = '<Process><Step No="1" Types="D1" Temp="1" Secs="61" Macro="21">Enable Mixers1</Step>
<Step No="11" Types="D11" Temp="11" Secs="611" Macro="21">Enable Mixers2</Step>
<Step No="111" Types="D111" Temp="111" Secs="6111" Macro="23">Enable Mixers3</Step></Process>'
--Create an internal representation of the XML document.
-- Reads the XML text -> parses the text by using the MSXML parser -> and provides the parsed document in a state ready for consumption.
EXEC sp_xml_preparedocument #idoc OUTPUT, #xml;
--SELECT
-- No as StepNumber,
-- Types as Types,
-- Temp as Temp,
-- Secs as Secs,
-- Macro as Macro,
-- NoteValue
--FROM OPENXML (#idoc, '/Process/Step')
-- WITH (
-- -- When OPENXML does not have input of third parameter then we can choose if this will atribute or node
-- -- usig '#No' will bring the value of atribute and using 'No' will bring the value of node
-- No INT '#No' ,
-- Types VARCHAR(128) '#Types',
-- Temp VARCHAR(128) '#Temp' ,
-- Secs VARCHAR(128) '#Secs' ,
-- Macro VARCHAR(128) '#Macro',
-- NoteValue VARCHAR(128) '.'
-- )
SELECT StepNumber, Column_Name, Column_Value
FROM(
SELECT
No as StepNumber,
Types as Types,
Temp as Temp,
Secs as Secs,
Macro as Macro
FROM OPENXML (#idoc, '/Process/Step',1)
WITH (
No INT,
Types VARCHAR(128),
Temp VARCHAR(128),
Secs VARCHAR(128),
Macro VARCHAR(128)
)
) p
UNPIVOT
(Column_Value FOR Column_Name IN (Types, Temp, Secs, Macro) )AS unpvt;
--sp_xml_removedocument free's up the memory.
EXEC sp_xml_removedocument #idoc
GO
So... we have multiple approaches whic fits different case... but we still need to think about tables...
Demo six: Using table, Step nodes has unknown structure, multiple Step nodes
You can implement Demo four if this fit (known structure or using dynamic query), but for the last demo I will implement Demo three approach on a case that we have multiple rows in a table which each row includes XML that has multiple Step nodes
DROP TABLE IF EXISTS MyXML_Tbl
GO
CREATE TABLE MyXML_Tbl(ID INT IDENTITY(1,1), MyXML XML)
GO
INSERT MyXML_Tbl(MyXML) VALUES
('<Process><Step No="1" Types="D1" Temp="1" Secs="61" Macro="21">Enable Mixers1</Step>
<Step No="11" Types="D11" Temp="11" Secs="611" Macro="21">Enable Mixers1</Step>
<Step No="111" Types="D111" Temp="111" Secs="6111" Macro="23">Enable Mixers3</Step></Process>')
INSERT MyXML_Tbl(MyXML) VALUES
('<Process><Step No="2" Types="D1" Temp="11" Secs="61" Macro="21">Enable Mixers1</Step>
<Step No="22" Types="D1" Temp="11" Secs="61" Macro="21">Enable Mixers1</Step>
<Step No="222" Types="D2" Temp="22" Secs="62" Macro="23">Enable Mixers3</Step></Process>')
GO
--SELECT * FROM MyXML_Tbl
--GO
--SELECT
-- tb.ID,
-- tx.c.value('./#No', 'VARCHAR(128)') as StepNumber,
-- tx.c.query ('.') as Types
--from MyXML_Tbl tb
--CROSS APPLY tb.MyXML.nodes('Process/.[1]/*')as tx(c)
;With MyCTE01 as (
SELECT
tb.ID,
tx.c.value('./#No', 'VARCHAR(128)') as StepNumber,
tx.c.query ('.') as MyXML
from MyXML_Tbl tb
CROSS APPLY tb.MyXML.nodes('Process/.[1]/*')as tx(c)
)
SELECT
MyCTE01.id,
MyCTE01.StepNumber,
doc.Col.value('local-name(.[1])','VARCHAR(100)') ColumnName,
doc.Col.value('.[1]','VARCHAR(100)') ColumnValue
FROM MyCTE01
CROSS APPLY MyCTE01.MyXML.nodes('/Step/#*') doc(Col)
WHERE not doc.Col.value('local-name(.[1])','VARCHAR(100)') = 'No'
GO
I hope this is useful. It should cover all cases mentioned in the discussion
Related
Postgres use xpath_table parsing with xmlnamespaces
Can I use xpath_table parsing with xmlnamespaces drop table if exists _xml; create temporary table _xml (fbf_xml_id serial,str_Xml xml); insert into _xml(str_Xml) select '<DataSet1 xmlns="http://tempuri.org/DataSet_LocalMaMC.xsd"> <Stations> <ID>5</ID> </Stations> <Stations> <ID>1</ID> </Stations> <Stations> <ID>2</ID> </Stations> <Stations> <ID>10</ID> </Stations> <Stations> <ID/> </Stations> </DataSet1>' ; drop table if exists _y; create temporary table _y as SELECT * FROM xpath_table('FBF_xml_id','str_Xml','_xml', '/DataSet1/Stations/ID', 'true') AS t(FBF_xml_id int,ID text); select * from _y If I take of the xmlnamespaces it works fine. I thought to work with Xpath, but when there is null, it gives me wrong results.
With Postgres 10 or later, xmltable() is the preferred way to do this. You can easily specify a list of namespaces with that. SELECT fbf_xml_id, xt.id FROM _xml cross join xmltable(xmlnamespaces ('http://tempuri.org/DataSet_LocalMaMC.xsd' as x), '/x:DataSet1/x:Stations' passing str_xml columns id text path 'x:ID') as xt Note that in the XPath expression used for the xmltable() function, the tags are prefixed with the namespace alias defined in the xmlnamespaces option even though they are not prefixed in the input XML. Online example
Where to add a separator for mybatis collections(List)
Mapper.xml <insert id="courseUploads" parameterType="com.technoshinelabs.eduskill.bean.Course" useGeneratedKeys="true" keyColumn="id" keyProperty="id"> insert into course_uploads (course_id, training_provider_logo, assignment_material, course_image, trainer_image, created_date, updated_date) values( #{courseId}, <foreach item="Course" collection="trainingProviderPath" > #{Course} </foreach>, <foreach item="Course" collection="assignmentMaterialPath"> #{Course} </foreach>, #{courseImagePath}, <foreach item="Course" collection="trainerImagePath"> #{Course} </foreach>, now(), now() ) </insert> How do I add a separator for the above list(item="Course"), this list will have multiple data, each data needs to be separated by some separator, well the data needs to be stored in the database, please do help me on this.
You can use the separator attribute. e.g.) <foreach item="Course" collection="foo" separator="||"> #{Course} </foreach> Specifically, what of SQL do you want to generate?
OPENXML Leaves out xml rows that do not have the specified elements
I am running below query on SQL Server 2014 server but I can't understand why I am getting only one row in result. DECLARE #idoc int, #doc varchar(1000); SET #doc =' <ROOT> <Customer CustomerID="VINET" ContactName="Paul Henriot"> <Order CustomerID="VINET" EmployeeID="5" OrderDate="1996-07-04T00:00:00"> <OrderDetail OrderID="10248" ProductID="11" Quantity="12"/> <OrderDetail OrderID="10248" ProductID="42" Quantity="10"> <ReturnDetail ReturnOrderID="1111" ReturnDate="1996-08-04T00:00:00"/> </OrderDetail> </Order> </Customer> <Customer CustomerID="LILAS" ContactName="Carlos Gonzlez"> <Order CustomerID="LILAS" EmployeeID="3" OrderDate="1996-08-16T00:00:00"> <OrderDetail OrderID="10283" ProductID="72" Quantity="3"/> </Order> </Customer> </ROOT>'; --Create an internal representation of the XML document. EXEC sp_xml_preparedocument #idoc OUTPUT, #doc; -- SELECT stmt using OPENXML rowset provider SELECT * FROM OPENXML (#idoc, '/ROOT/Customer/Order/OrderDetail/ReturnDetail',2) WITH ( OrderID int '../#OrderID', order_CustomerID varchar(10) '../../#CustomerID', EmployeeID varchar(10) '../../#EmployeeID', ContactName varchar(100) '../../../#ContactName', CustomerID varchar(10) '../../#CustomerID', OrderDate datetime '../../#OrderDate', ProdID int '../#ProductID', Qty int '../#Quantity', ReturnOrderID int '#ReturnOrderID', ReturnDate datetime '#ReturnDate' ); How do I get all 3 records returned like below
You should use the built-in, native XQuery support (instead of the legacy OPENXML stuff...). Use this code to get all the details down to the <OrderDetail> node (define your #doc variable as XML): DECLARE #doc XML; SET #doc = '......'; SELECT OrderID = XOD.value('#OrderID', 'int'), CustomerID = XCus.value('#CustomerID', 'varchar(20)'), ContactName = XCus.value('#ContactName', 'varchar(50)'), EmployeeID = XOrder.value('#EmployeeID', 'int'), OrderDate = XOrder.value('#OrderDate', 'datetime'), ProductID = XOD.value('#ProductID', 'int'), Quantity = XOD.value('#Quantity', 'int'), ReturnOrderID = RetD.value('#ReturnOrderID', 'int'), ReturnDate = RetD.value('#ReturnDate', 'datetime') FROM #doc.nodes('/ROOT/Customer') AS XT(XCus) CROSS APPLY XCus.nodes('Order') AS XT2(XOrder) CROSS APPLY XOrder.nodes('OrderDetail') AS XT3(XOD) OUTER APPLY XOD.nodes('ReturnDetail') AS XT4(RetD) For each "level" that might contain multiple nodes (like <Customer> under <ROOT> etc.), you need to use CROSS APPLY and the .nodes() XQuery function to get all the child nodes - not just one (first or arbitrary).
Inserting many rows in treelike structure in SQL SERVER 2005
I have a few tables in SQL that are pretty much like this A B C ID_A ID_B ID_C Name Name Name ID_A ID_B As you can see, A is linked to B and B to C. Those are basically tables that contains data models. Now, I would need to be able to create date based on those tables. For example, if I have the following datas A B C 1 Name1 1 SubName1 1 1 SubSubName1 1 2 Name2 2 SubName2 1 2 SubSubName2 1 3 SubName3 2 3 SubSubName3 2 4 SubSubName4 3 5 SubSubName5 3 I would like to copy the 'content' of those tables in others tables. Of course, the auto numeric key that is generated when inserting into the new tables are diffirent that those one and I would like to be able to keep track so that I can copy the entire thing. The structure of the recipient table contains more information that those, but it's mainly dates and other stuff that are easy to get for me. I would need to this entirely in TRANSACT-SQL (with built-in function if needed). Is this possible and can anyone give me a short example. I manage to do it for one level, but I get confused for the rest. thanks EDIT : The info above is just an example, because my actual diagram looks more like this Model tables : Processes -- (1-N) Steps -- (1-N) Task -- (0-N) TaskCheckList -- (0-N) StepsCheckLists Where as the table I need to fill looks like this Client -- (0-N) Sequence -- (1-N) ClientProcesses -- (1-N) ClientSteps -- (1-N)ClientTasks -- (0-N) ClientTaskCheckList -- (0-N)ClientStepCheckLists The Client already exists and when I need to run the script, I create one sequence, which will contains all processes, which will contains its steps, taks, etc...
Ok, So I did a lot of trials and error, and here is what I got. It seems to work fine although it sound quite big for something that seemed easy at first. The whole this is somehow in french and english because our client is french and so are we anyway. It does insert every date in all tables that I needed. The only thing left to this will be the first lines where I need to select the date to insert according to some parameters but this is the easy part. DECLARE #IdProcessusRenouvellement bigint DECLARE #NomProcessus nvarchar(255) SELECT #IdProcessusRenouvellement = ID FROM T_Ref_Processus WHERE Nom LIKE 'EXP%' SELECT #NomProcessus = Nom FROM T_Ref_Processus WHERE Nom LIKE 'EXP%' DECLARE #InsertedSequence table(ID bigint) DECLARE #Contrats table(ID bigint,IdClient bigint,NumeroContrat nvarchar(255)) INSERT INTO #Contrats SELECT ID,IdClient,NumeroContrat FROM T_ClientContrat DECLARE #InsertedIdsSeq as Table(ID bigint) -- Séquences de travail INSERT INTO T_ClientContratSequenceTravail(IdClientContrat,Nom,DateDebut) OUTPUT Inserted.ID INTO #InsertedIdsSeq SELECT ID, #NomProcessus + ' - ' + CONVERT(VARCHAR(10), GETDATE(), 120) + ' : ' + NumeroContrat ,GETDATE() FROM #Contrats -- Processus DECLARE #InsertedIdsPro as Table(ID bigint,IdProcessus bigint) INSERT INTO T_ClientContratProcessus (IdClientContratSequenceTravail,IdProcessus,Nom,DateDebut,DelaiRappel,DateRappel,LienAvecPro cessusRenouvellement,IdStatutProcessus,IdResponsable,Sequence) OUTPUT Inserted.ID,Inserted.IdProcessus INTO #InsertedIdsPro SELECT I.ID,P.ID,P.Nom,GETDATE(),P.DelaiRappel,GETDATE(),P.LienAvecProcessusRenouvellement,0,0,0 FROM #InsertedIdsSeq I, T_Ref_Processus P WHERE P.ID = #IdProcessusRenouvellement -- Étapes DECLARE #InsertedIdsEt as table(ID bigint,IdProcessusEtape bigint) INSERT INTO T_ClientContratProcessusEtape (IdClientContratProcessus,IdProcessusEtape,Nom,DateDebut,DelaiRappel,DateRappel,NomListeVeri fication,Sequence,IdStatutEtape,IdResponsable,IdTypeResponsable,ListeVerificationTermine) OUTPUT Inserted.ID,Inserted.IdProcessusEtape INTO #InsertedIdsEt SELECT I.ID,E.ID, E.Nom,GETDATE(),E.DelaiRappel,GETDATE(),COALESCE(L.Nom,''),E.Sequence,0,0,E.IdTypeResponsabl e,0 FROM #InsertedIdsPro I INNER JOIN T_Ref_ProcessusEtape E ON I.IdProcessus = E.IdProcessus LEFT JOIN T_Ref_ListeVerification L ON E.IdListeVerification = L.ID -- Étapes : Items de la liste de vérification INSERT INTO T_ClientContratProcessusEtapeListeVerificationItem (IdClientContratProcessusEtape,Nom,Requis,Verifie) SELECT I.ID,IT.Nom,IT.Requis,0 FROM #InsertedIdsEt I INNER JOIN T_Ref_ProcessusEtape E ON I.IdProcessusEtape = E.ID INNER JOIN T_Ref_ListeVerificationItem IT ON E.IdListeVerification = IT.IdListeVerification -- Tâches DECLARE #InsertedIdsTa as table(ID bigint, IdProcessusEtapeTache bigint) INSERT INTO T_ClientContratProcessusEtapeTache (IdClientContratProcessusEtape,IdProcessusEtapeTache,Nom,DateDebut,DelaiRappel,DateRappel,No mListeVerification,Sequence,IdStatutTache,IdResponsable,IdTypeResponsable,ListeVerificationT ermine) OUTPUT Inserted.ID,Inserted.IdProcessusEtapeTache INTO #InsertedIdsTa SELECT I.ID,T.ID, T.Nom,GETDATE(),T.DelaiRappel,GETDATE(),COALESCE(L.Nom,''),T.Sequence,0,0,T.IdTypeResponsabl e,0 FROM #InsertedIdsEt I INNER JOIN T_Ref_ProcessusEtapeTache T ON I.IdProcessusEtape = T.IdProcessusEtape LEFT JOIN T_Ref_ListeVerification L ON T.IdListeVerification = L.ID -- Tâches : Items de la liste de vérification INSERT INTO T_ClientContratProcessusEtapeTacheListeVerificationItem (IdClientContratProcessusEtapeTache,Nom,Requis,Verifie) SELECT I.ID,IT.Nom,IT.Requis,0 FROM #InsertedIdsTa I INNER JOIN T_Ref_ProcessusEtapeTache T ON I.IdProcessusEtapeTache = T.ID INNER JOIN T_Ref_ListeVerificationItem IT ON T.IdListeVerification = IT.IdListeVerification
Generate XML from Table
I have a table like this: ID Name Column1 Column2 Column3 1 ABC 202.2 1500 34000 2 IJK 104 10000 27000 I want to generate XML like this: <doc> <record ID="1" Name="ABC" Column1="202.2" Column2="15000" Column3="34000" /> <record ID="2" Name="IJK" Column1="104" Column2="10000" Column3="27000" /> </doc> I have got some clue from this forum post and used this code: CREATE TABLE #tmp (column1 VARCHAR(20), column2 VARCHAR(20), column3 VARCHAR(20)) INSERT INTO #tmp VALUES ( 'data1', 'data2', 'data3' ) INSERT INTO #tmp VALUES ( 'data11', 'data21', 'data31' ) -- FOR XML PATH with ELEMENTS will automatically unpivot the data for you -- Then reshape your XML using nested FLWOR loops SELECT ( SELECT * FROM #tmp t FOR XML PATH, ELEMENTS, TYPE ).query(' for $e in row return <row>{ for $f in $e/* return <field name="{local-name($f)}">{data($f)}</field> } </row> ') I tried the following modified version: SELECT (SELECT * FROM cte_temp t FOR XML PATH, ELEMENTS, TYPE) .query('for $e in row return <doc> { for $f in $e return <record {local-name($f)}="{data($f)}" /> } </doc>') But I'm getting error: XQuery [query()]: Invalid source character 0x7b found in an identifier near 'return'.
Why you trying to get fancy. Select * from #tmp as record FOR XML AUTO, root('doc')