tsql for xml path insert mutliple the same named rows - sql-server

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>

Related

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 dynamically insert data in respective tables based upon xml in Sql server

I have this type of input XML parameter pass in stored procedure, which is passed from my .net application.
Now, I need to insert records in each respective table:
<root>
<table1>
<patid>123</patid>
<name>gresh</name>
<fname>kumar</name>
</table1>
<table2>
<patid>123</patid>
<Schoolname>12345</Schoolname>
</table2>
<tablen>
<patid>123</patid>
<nfield>12345</nfield>
</tablen>
<root>
Suppose table1 will insert data in table1, table2 data in table2, tablen mean number of other tables may be there in XML.
So how it would be possible to insert in each respective tables?
You first need to get the data from the XML. Your case is pretty simple (and I am assuming you are inserting data only in one table only once, but you can solve it for multiple insertions in one table easily). So, the following statement gives me:
SELECT T.c.value('local-name(.)','nvarchar(128)') AS tableName
,T1.c1.value('local-name(.)','nvarchar(128)') AS columName
,T1.c1.value('(./node())[1]','nvarchar(max)') AS value
FROM #XML.nodes('/root/*') T(c)
CROSS APPLY T.c.nodes('*') T1(c1)
Then, you need to group the values for insertion for each table (I am using a CLR concatenate function (you can find it here, but you can search for T-SQL alternative also):
;WITH DataSource(tableName, columName, value)AS
(
SELECT T.c.value('local-name(.)','nvarchar(128)')
,T1.c1.value('local-name(.)','nvarchar(128)')
,T1.c1.value('(./node())[1]','nvarchar(max)')
FROM #XML.nodes('/root/*') T(c)
CROSS APPLY T.c.nodes('*') T1(c1)
)
SELECT tableName
,[dbo].[Concatenate] (columName)
,[dbo].[Concatenate] (value)
FROM DataSource
GROUP BY tableName
You can prepare the above code for dynamic execution further like this:.
;WITH DataSource(tableName, columName, value)AS
(
SELECT T.c.value('local-name(.)','nvarchar(128)')
,T1.c1.value('local-name(.)','nvarchar(128)')
,T1.c1.value('(./node())[1]','nvarchar(max)')
FROM #XML.nodes('/root/*') T(c)
CROSS APPLY T.c.nodes('*') T1(c1)
)
SELECT 'INSERT INTO ' + tableName + '(' + [dbo].[Concatenate] (columName) + ') VALUES(' + [dbo].[Concatenate] ('''' + value + '''') + ');'
FROM DataSource
GROUP BY tableName
Now, you simple need to build a dynamic T-SQL string and execute it using sp_executesql procedure:
DECLARE #XML XML = N'<root>
<table1>
<patid>123</patid>
<name>gresh</name>
<fname>kumar</fname>
</table1>
<table2>
<patid>123</patid>
<Schoolname>12345</Schoolname>
</table2>
<tablen>
<patid>123</patid>
<nfield>12345</nfield>
</tablen>
</root>';
DECLARE #DynamicSQLStatement NVARCHAR(MAX)
;WITH DataSource(tableName, columName, value)AS
(
SELECT T.c.value('local-name(.)','nvarchar(128)')
,T1.c1.value('local-name(.)','nvarchar(128)')
,T1.c1.value('(./node())[1]','nvarchar(max)')
FROM #XML.nodes('/root/*') T(c)
CROSS APPLY T.c.nodes('*') T1(c1)
)
SELECT #DynamicSQLStatement =
(
SELECT CHAR(10) + 'INSERT INTO ' + tableName + '(' + [dbo].[Concatenate] (columName) + ') VALUES(' + [dbo].[Concatenate] ('''' + value + '''') + ');'
FROM DataSource
GROUP BY tableName
FOR XML PATH, TYPE
).value('.', 'NVARCHAR(MAX)')
PRINT #DynamicSQLStatement
EXEC sp_executesql #DynamicSQLStatement
Note, that I am assuming that your XML structure is valid in the context of the database - the table exists, the column exists, and the values inserted in the columns are correct.
You can add more check if you need.

Grouping XML Elements in FOR XML Clause

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');

How to merge multiple rows in one single column field with given condition in SQL SERVER 2008 [duplicate]

This question already has answers here:
Combine multiple results in a subquery into a single comma-separated value
(10 answers)
Closed 9 years ago.
I am using SQL Server 2008 and I need to implement this :->
I get a result like this :
Table:-sql query ..............
acc_no name
001-000001 John
001-000001 Bob
001-000001 James
001-000002 Sam
001-000002 Bin
001-000002 Dus
So, the condition is that; multiple persons can have same acc_no. So i want following result:
acc_no name
001-000001 John,Bob,James
001-000002 Sam,Bin,Dus
There are other conditions for displaying the results but I got stuck in displaying this format.
How about something like
DECLARE #Table TABLE(
acc_no VARCHAR(50),
name VARCHAR(50)
)
INSERT INTO #Table (acc_no,name) SELECT '001-000001', 'John'
INSERT INTO #Table (acc_no,name) SELECT '001-000001', 'Bob'
INSERT INTO #Table (acc_no,name) SELECT '001-000001', 'James'
INSERT INTO #Table (acc_no,name) SELECT '001-000002', 'Sam'
INSERT INTO #Table (acc_no,name) SELECT '001-000002', 'Bin'
INSERT INTO #Table (acc_no,name) SELECT '001-000002', 'Dus'
--Concat
SELECT t.acc_no,
stuff(
(
select ',' + t1.name
from #Table t1
where t1.acc_no = t.acc_no
order by t1.name
for xml path('')
),1,1,'') Concats
FROM #Table t
GROUP BY t.acc_no
SQL Fiddle DEMO
Try this one -
DECLARE #temp TABLE
(
ID VARCHAR(20)
, Name VARCHAR(50)
)
INSERT INTO #temp (ID, Name)
VALUES
('001-000001', 'John'),
('001-000001', 'Bob'),
('001-000001', 'James'),
('001-000002', 'Sam'),
('001-000002', 'Bin'),
('001-000002', 'Dus')
SELECT t.ID, STUFF((
SELECT ', ' + t2.Name
FROM #temp t2
WHERE t.ID = t2.ID
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, '')
FROM (
SELECT DISTINCT ID
FROM #temp
) t
Output -
ID
-------------------- -------------------
001-000001 John, Bob, James
001-000002 Sam, Bin, Dus
select acc_no,stuff((SELECT distinct ', ' + cast(name as varchar(10))
FROM yourtable t2
where t2.acc_no = t1.acc_no
FOR XML PATH('')),1,1,'')
from yourtable t1
group by acc_no

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