Grouping XML Elements in FOR XML Clause - sql-server

I am trying to create a structure xml document from my temp table .The temp table is in the following format .
CREATE TABLE #Temp1 ( Name Char( 30 ), seqid integer, salary int );
INSERT INTO #Temp1 VALUES('DEAL' ,123,6)
INSERT INTO #Temp1 VALUES('DEAL' ,56,6)
INSERT INTO #Temp1 VALUES('TRACNHE' ,1253,56)
INSERT INTO #Temp1 VALUES('TRACNHE' ,5,65)
INSERT INTO #Temp1 VALUES('ASSET' ,56,23)
I am trying to create an xml format in the following form :
<Response>
<Deal>
<seqid="123" salary="6" />
<seqid="56" salary="6" />
<Deal>
<TRACNHE>
<seqid="1253" salary="56"/>
<seqid="5" salary="65"/>
</TRACNHE>
<ASSET>
<seqid="56" salary="23"/>
</ASSET>
</Response>
SELECT Name, (SELECT SEQID FROM #TEMP1 T WHERE T.Name = T1.Name)
FROM (SELECT DISTINCT NAME FROM #TEMP1 ) T1
FOR XML PATH('rEPONSE')
DROP TABLE #Temp1
DROP TABLE #Temp1
I tried the above query but says that subquery returned more than 1 value
Could you let me know as to what i am missing in this query .
Is there a better way to handle this scenario.
Thanks in advance

based on your requirement, i'm seeing there are 2 types of complexities
You are trying to get the xml with grouped items.
For each group trying to create an xml element with two attributes
without any proper name
<seqid="1253" salary="56"/>
instead of
<ss seqid="1253" salary="56"/>
just look into this below query, it may help
SELECT
(SELECT
seqid 'ss/#seqid'
, salary 'ss/#salary'
FROM Temp1 as t where t.Name = 'Deal'
FOR XML PATH('Deal') , TYPE
) ,
(SELECT
seqid 'ss/#seqid'
, salary 'ss/#salary'
FROM Temp1 as t where t.Name = 'TRACNHE'
FOR XML PATH('TRACNHE') , TYPE
) ,
(SELECT
seqid 'ss/#seqid'
, salary 'ss/#salary'
FROM Temp1 as t where t.Name = 'ASSET'
FOR XML PATH('ASSET') , TYPE
)
FOR XML PATH(''), ROOT('Response');

Related

Insert multiple rows of data with out looping the table data

I have a table where it holds some duplicate entries, I would like to copy over the distinct entries to another table with out looping the data. I need to check if the distinct data exists in other table and insert what ever is missing. Here is the query I am writing, I feel like it can be implement better
CREATE TABLE ForgeRock
([productName] varchar(13));
INSERT INTO ForgeRock
([productName])
VALUES
('OpenIDM'), ('OpenAM'), ('OpenDJ'), ('OpenDJ'),('OpenDJ1');
CREATE TABLE ForgeRock1
([productName] varchar(13));
DECLARE #prodName NVARCHAR(MAX)
SELECT DISTINCT #prodName = STUFF((SELECT ',' + productName
FROM ForgeRock
FOR XML PATH('')) ,1,1,'')
set #prodName = ''''+replace(#prodName,',',''',''')+''''
INSERT INTO ForgeRock1 (productName)
SELECT DISTINCT productName FROM ForgeRock WHERE
productName NOT IN (SELECT productName FROM ForgeRock1
where productName NOT IN (#prodName))
Here is the sample fiddle I tried out http://sqlfiddle.com/#!18/9dbe8f/1/0, is this query efficient or can it be better
This query should do what you want :)
INSERT INTO ForgeRock1 (productName)
SELECT DISTINCT productName FROM ForgeRock fr
WHERE NOT EXISTS ( SELECT 1 FROM ForgeRock1 fr1 WHERE fr1.productName = fr.productName )

tsql for xml path insert mutliple the same named rows

Lets say I have table T with one column A.
What I would like to achieve as result is xml like this :
<not>
<mes>not important what include</mes>
<A>1</A>
<A>2</A>
<A>3</A>
<A>4</A>
...
</not>
Was trying something similar to :
SELECT
'important' AS [mes],
(select A as [A] from T)- of course that part is incorrect but don't know how to handle it
FROM T2
FOR XML PATH ('not');
Please advice.
Updated QUERY
SET #SQL = '
WITH XMLNAMESPACES (''https://something..'' as ns)
SELECT
Q.DocumentType AS [#type],
Q.ReferenceNo AS [#ref],
Q.Id AS [#id],
D.DocId AS [#docId],
N.NotId AS [#notId],
CONVERT(char(10), N.CreationDate, 126) AS [#notdate],
''mes'' AS [mes/#content],
#mes2 AS [mes/content],
[mes] = ''important'' ,
(select A from '+ Cast(#TableName as VARCHAR(60))+' FOR XML PATH (''''), type)
FROM
[DB].[dbo].[tab1] AS Q
LEFT JOIN [DB].[dbo].[tab2] AS D ON Q.ID=D.ID
LEFT JOIN [DB].[dbo].[tab3] AS N ON D.ID=N.DocId
WHERE
Q.ID='+ Cast(#Id as varchar(15))+'
FOR XML PATH (''not'')';
execute (#SQL);
Perhaps this will help
-- Just a DEMONSTRATIVE Table Variable
--------------------------------------------
Declare #YourTable Table ([A] varchar(50))
Insert Into #YourTable Values
(1)
,(2)
,(3)
,(4)
SELECT [mes] = 'important'
,( Select A from #YourTable For XML Path(''),type )
FOR XML PATH ('not');
Results
<not>
<mes>important</mes>
<A>1</A>
<A>2</A>
<A>3</A>
<A>4</A>
</not>

How to parse XML from table in SQL Server

I have data in XML in column in table
SELECT ObjectXML
FROM DispOps_Events
[ObjectXML] [nvarchar](max) NOT NULL
A sample of the XML data:
<Document>
<DocumentId>3352597</DocumentId>
<DocumentFullPath>xxx</DocumentFullPath>
<Category>xxx</Category>
<ClientId>xxx</ClientId>
<ApplicationNumber>xxx</ApplicationNumber>
<ContractNumber>xxx</ContractNumber>
<Created>xxx</Created>
<Creator>xxx</Creator>
</Document>
And I need get data from DocumentId>XXXX/DocumentId> and insert into #tmpTable.
So 1. I cast varchar(max) to xml
select CAST(ObjectXML as XML) as fileXML
INTO #tmpXML
FROM DispOps_Events T WHERE MetastormMapName = 'DocumentsMap'
I tried
select
m.c.value('#DocumentId', 'varchar(max)') as DocumentId
--into #tmpTable
from #tmpXML as s
outer apply s.fileXML.nodes('Document/DocumentId') as m(c)
Error:
null data in the table
You don't need #temp tables to do this, you can just cast the nvarchar(max) data to the xml data type in a single query, e.g.:
/*
* Setup test data...
*/
drop table if exists dbo.DispOps_Events;
create table dbo.DispOps_Events (
ID int not null identity(1,1),
ObjectXML nvarchar(max)
);
insert dbo.DispOps_Events (ObjectXML) values
(N'<Document><DocumentId>2554742</DocumentId><!--...--></Document>'),
(N'<Document><DocumentId>2576868</DocumentId><!--...--></Document>'),
(N'<Document><DocumentId>2576869</DocumentId><!--...--></Document>'),
(N'<Document><DocumentId>2576870</DocumentId><!--...--></Document>');
/*
* Query XML...
*/
select ID, [DocumentId] = Document.DocumentId.value('text()[1]', 'nvarchar(50)')
from dbo.DispOps_Events
cross apply ( select try_cast(ObjectXML as xml) ) Transformers(RoolyTroolyXml)
cross apply RoolyTroolyXml.nodes('/Document/DocumentId') as Document(DocumentId);
ID
DocumentId
1
2554742
2
2576868
3
2576869
4
2576870

Joining with Temp table outside XML element

I am new to XML+SQL module and I have a code that selects a regular column and a whole bunch of XML data.
Below is my sample code:
create table #temp(cid int, val int)
insert into #temp values
(1,11),
(2,12),
(3,12)
select
t1.cid,
xml =
(
select t2.cid,t2.val
from #temp t2
join #temp t1 on t2.cid = t1.cid
for xml Path(''), type)
from #temp t1
drop table #temp
desired output is:
Rexter link: http://rextester.com/HLZS59752
Any help ??
If I understand your question.
Example
select
t1.cid,
xml = (Select t1.* for xml path('') )
from #temp t1
Returns
cid xml
1 <cid>1</cid><val>11</val>
2 <cid>2</cid><val>12</val>
3 <cid>3</cid><val>12</val> -- Last record in #temp is (3,12)
Thanks #John Cappelletti for that answer. That helped. One mroe solution I found was:
select
t1.cid,
xml =
(
select t2.cid,t2.val
from #temp t2
where t1.cid = t2.cid
for xml Path(''), type)
from #temp t1
Instead of join, I added the condition in Where clause and it worked.
Updated Rexter link: http://rextester.com/MGXDC39580

How to create view or function on XML PATH query?

I am using SSMS 2008 with the following query:
DECLARE #TestData TABLE
(
address_desc NVARCHAR(100) NULL
,people_id UNIQUEIDENTIFIER NULL
);
INSERT #TestData
SELECT a.address_desc, a.people_id
FROM dbo.address_view a
SELECT a.people_id,
(SELECT SUBSTRING(
(SELECT ';'+b.address_desc
FROM #TestData b
WHERE a.people_id = b.people_id
FOR XML PATH(''))
,2
,4000)
) GROUP_CONCATENATE
FROM #TestData a
GROUP BY a.people_id
This query works, but I want to make this into a view or function so that I can call it from different stored procs. How can I do this? From what I understand, variables cannot be declared in VIEW statements.
Hong, here is my updated query based on your advice which gives me errors:
DECLARE #TestData TABLE
(
address_desc NVARCHAR(100) NULL
,people_id UNIQUEIDENTIFIER NULL
);
INSERT #TestData
SELECT a.address_desc, a.people_id FROM dbo.address_view a
SELECT a.people_id,
(SELECT address_desc, people_id FROM dbo.address_view),
(SELECT SUBSTRING(
(SELECT ';'+b.address_desc
FROM #TestData b
WHERE a.people_id = b.people_id
FOR XML PATH(''))
,2
,4000)
) GROUP_CONCATENATE
FROM #TestData a
GROUP BY a.people_id
In your last select query replace #TestData with subquery (SELECT address_desc, people_id FROM dbo.address_view), and then get rid of temp table #TestData.
Try this:
Create View YourView As
SELECT a.people_id,
(SELECT SUBSTRING(
(SELECT ';'+b.address_desc
FROM (SELECT address_desc, people_id FROM dbo.address_view) b
WHERE a.people_id = b.people_id
FOR XML PATH(''))
,2
,4000)
) GROUP_CONCATENATE
FROM (SELECT address_desc, people_id FROM dbo.address_view) a
GROUP BY a.people_id

Resources