Read XML data in SQL Server 2012 - sql

I want to read xml data in the xml file.
I have a table column consist with the xml data.
if i click on the xml file it will open in the Sql server Management studio.
xml file format shown below.
I want to read only NTDomainName, DatabaseName and ServerName and write that data in the another Table. Table format shown below
NTDomainName | DatabaseName | ServerName
----------
ABC | TestCube1 | SERXYZ

Try this:
declare #xml xml
set #xml = '<event><data name="NTUserName"><value>MyName</value></data><data name="NTDomainName"><value>DomainName</value></data><data name="ServerName"><value>ServerName</value></data></event>'
select [NTDomainName], [DatabaseName], [ServerName] from
(
select [name],[value] from (
select c.value('./#name', 'varchar(100)') [name], c.value('(./value)[1]', 'varchar(100)') [value]
from #xml.nodes('/event/data') as t(c)
) a where [name] in ('NTDomainName', 'DatabaseName', 'ServerName')
) x
pivot (
max(value) for [name] in ([NTDomainName], [DatabaseName], [ServerName])
) as [pivot_Name]
The most inner query will retrieve information from XML, one row for every name attribute value, that you want to retrieve. So, output of this query needs to be pivoted.

i think you look for this:
SELECT * FROM (
SELECT
CAST(f.x.query('data(#name)') as varchar(150)) as data_name,
CAST(f.x.query('data(value)') as varchar(150)) as data_value
FROM #xml.nodes('/event') as t(n)
CROSS APPLY t.n.nodes('data') as f(x)) X
PIVOT (MAX(data_value) FOR data_name IN (NTDomainName, DatabaseName, ServerName)) as pvt

If you do not want to use PIVOT:
DECLARE #DataSource TABLE
(
[ID] TINYINT IDENTITY(1,1)
,[XML] XML
);
INSERT INTO #DataSource ([XML])
VALUES ('<event><data name="SessionID">S1</data><data name="NTUserName">User1</data><data name="DatabaseName">DB1</data><data name="ServerName">SN1</data></event>')
,('<event><data name="SessionID">S1</data><data name="NTUserName">User2</data><data name="DatabaseName">DB2</data><data name="ServerName">SN2</data></event>');
SELECT [ID]
,MAX(CASE wHEN C.value('(./#name)[1]', 'varchar(50)') = 'NTUserName' THEN C.value('(.)[1]', 'varchar(50)') END) AS [NTUserName]
,MAX(CASE wHEN C.value('(./#name)[1]', 'varchar(50)') = 'DatabaseName' THEN C.value('(.)[1]', 'varchar(50)') END) AS [DatabaseName]
,MAX(CASE wHEN C.value('(./#name)[1]', 'varchar(50)') = 'ServerName' THEN C.value('(.)[1]', 'varchar(50)') END) AS [ServerName]
FROM #DataSource
CROSS APPLY [XML].nodes('event/data[#name = "NTUserName" or #name = "DatabaseName" or #name = "ServerName"]') T(c)
GROUP BY [ID];

Related

Import xml data in SQL Server 2017

I have XML data like this:
<?xml version="1.0" ?>
<SettlementFile>
<Transaction>
<Identifier>
<StationID>049215901 </StationID>
<TransactionTimestamp>2021-04-01T10:39:32</TransactionTimestamp>
</Identifier>
<TerminalInfo>
<TerminalID>21590151</TerminalID>
<TerminalType>2</TerminalType>
</TerminalInfo>
<TransactionInfo>
<TransactionType>0</TransactionType>
<TransactionAmount>3.74</TransactionAmount>
<CurrencyCode>978</CurrencyCode>
<CustomerInput>
<Mileage>0</Mileage>
</CustomerInput>
<TicketNumber>213510037</TicketNumber>
<AuthorisationType>1</AuthorisationType>
</TransactionInfo>
</Transaction>
</SettlementFile>
My SQL Server table structure:
CREATE TABLE dbo.Import_Oase
(
StationID varchar(50) NULL,
TransactionTimestamp datetime NULL,
TicketNumber int NULL,
Mileage varchar(50) NULL
) ON PRIMARY
I'm trying to use this SELECT query:
SELECT
MY_XML.Details.query('StationID') .value('.', 'VARCHAR(50)'),
MY_XML.Details.query('TransactionTimestamp').value('.', 'Datetime'),
MY_XML.Details.query('TicketNumber') .value('.', 'Integer'),
MY_XML.Details.query('Mileage') .value('.', 'VARCHAR(50)')
FROM
(SELECT
CAST(MY_XML AS XML)
FROM
OPENROWSET(BULK '\\EO-TEST\SQL-Daten\Temp\MY_XML.xml', SINGLE_BLOB) AS T(MY_XML)
) AS T(MY_XML)
CROSS APPLY
MY_XML.nodes('SettlementFile/Transaction/Identifier, SettlementFile/Transaction/TransactionInfo, SettlementFile/Transaction/TransactionInfo/CustomerInput') AS MY_XML (Details);
I need to get the result in one line because it is all for 1 transactions. But it is in three different line in SQL.
Please try the following solution.
When you are satisfied with the outcome, just uncomment the INSERT INTO line.
SQL
WITH rs (xmlData) AS
(
SELECT TRY_CAST(BulkColumn AS XML)
FROM OPENROWSET(BULK N'e:\Temp\ daryosmitan.xml', SINGLE_BLOB) AS x
)
-- INSERT INTO dbo.Import_Oase (StationID, TransactionTimestamp, TicketNumber, Mileage)
SELECT c.value('(Identifier/StationID/text())[1]', 'VARCHAR(50)') AS StationID
, c.value('(Identifier/TransactionTimestamp/text())[1]', 'DATETIME') AS TransactionTimestamp
, c.value('(TransactionInfo/TicketNumber/text())[1]', 'VARCHAR(50)') AS TicketNumber
, c.value('(TransactionInfo/CustomerInput/Mileage/text())[1]', 'INT') AS Mileage
FROM rs
CROSS APPLY xmlData.nodes('/SettlementFile/Transaction') AS t(c);

Sql server separate a string and pivot the result

I have a string that a get from a query, and separate by delimiter:
After that i need to put in columns instead of rows, this is what i'm doing from searching examples.
Declare #NomeAux varchar(255)
Declare #id int = 3059
select #NomeAux = des_auxiliar from WKF_ProcessoItem where Id_ProcessoItem = #id
SELECT #id as id,Split.a.value('.', 'NVARCHAR(MAX)') valores
into #temp
FROM
(
SELECT CAST('<X>'+REPLACE(#NomeAux, ';', '</X><X>')+'</X>' AS XML) AS String
) AS A
CROSS APPLY String.nodes('/X') AS Split(a);
SELECT
Id
, [GSE]
, [LOCAL]
, [SN]
, [Modelo]
, [Fechadura]
, [Vazio]
FROM #temp
PIVOT (
max(valores)
FOR valores IN ([GSE], [LOCAL], [SN],[Modelo],[Fechadura],[Vazio])
) AS PIVOTED
But I'm getting all values null like this:
I'm getting all values null
The result I need
This looks like a pretty strange way to store a EAV list (Entity-Attribute-Value), where the id marks the entity and the text is a name-value-pair. Try something along this:
DECLARE #tbl TABLE(id INT,valores VARCHAR(100));
INSERT INTO #tbl VALUES
(1,'[GSE] SAO')
,(1,'NOME DO LOCAL: CASH')
,(1,'SN:1111')
,(1,'MODELO: blah1')
,(1,'FECHADURA: 11')
,(2,'[GSE] SAO')
,(2,'NOME DO LOCAL: CREDIT')
,(2,'SN:2222')
,(2,'MODELO: blah2')
,(2,'FECHADURA: 22');
SELECT t.id
,MAX(CASE WHEN valoresXml.value('/x[1]/text()[1]','nvarchar(max)')='[GSE] SAO' THEN t.valores END) AS GSE
,MAX(CASE WHEN valoresXml.value('/x[1]/text()[1]','nvarchar(max)')='NOME DO LOCAL' THEN valoresXml.value('/x[2]/text()[1]','nvarchar(max)') END) AS NomeDoLocal
,MAX(CASE WHEN valoresXml.value('/x[1]/text()[1]','nvarchar(max)')='SN' THEN valoresXml.value('/x[2]/text()[1]','nvarchar(max)') END) AS SN
,MAX(CASE WHEN valoresXml.value('/x[1]/text()[1]','nvarchar(max)')='MODELO' THEN valoresXml.value('/x[2]/text()[1]','nvarchar(max)') END) AS Modelo
,MAX(CASE WHEN valoresXml.value('/x[1]/text()[1]','nvarchar(max)')='FECHADURA' THEN valoresXml.value('/x[2]/text()[1]','nvarchar(max)') END) AS Fechadura
FROM #tbl t
CROSS APPLY(SELECT CAST('<x>' + REPLACE(t.valores,':','</x><x>') + '</x>' AS XML)) A(valoresXML)
GROUP BY t.id;
The result
id GSE NomeDoLocal SN Modelo Fechadura
1 [GSE] SAO CASH 1111 blah1 11
2 [GSE] SAO CREDIT 2222 blah2 22
The idea in short:
This technique is called "conditional aggregation" (kind of old-fashioned pivot).
We use XML to divide the text at the :-character (What about [GSE] SAO?).
We return a grouped set with the values taken conditionally.

Pivot based on Data

How do I achieve this output
TableName: Test
Code Description
A Apple
B Ball
C Cat
Output: Query
Apple Ball Cat
A B C
If you are using SQL server means use below PIVOT table :
CREATE TABLE #Table(Code VARCHAR(1), Description VARCHAR(15) )
INSERT INTO #Table(Code , Description )
SELECT 'A','Apple' UNION ALL
SELECT 'B','Ball' UNION ALL
SELECT 'C','Cat'
SELECT *
FROM
(
SELECT Code , Description
FROM #Table
) A
PIVOT
(
MAX(Code) FOR Description IN ([Apple],[Ball],[Cat])
)pvt
Edit : For dynamic pivot
DECLARE #DynamicString VARCHAR(MAX) = '' , #DynamicPvt VARCHAR(MAX) = ''
SELECT #DynamicString =
(
SELECT STUFF ((SELECT ',' + RTRIM(Description) FROM #Table FOR XML
PATH('')),1,1,'')
)
SET #DynamicPvt = 'SELECT *
FROM
(
SELECT Code , Description FROM #Table
)A
PIVOT
(
MAX(Code) FOR Description IN ('+#DynamicString+')
)
PVt'
EXEC (#DynamicPvt)

SQL Script to Break up XML into Columns

I have a table that stores audit history in an XML format. Each document has its own history. How can I parse out he XML data per document whereby each column in the XML represents and an actual column and action that took place in that column.
Example:
<auditElement><field id="2881159" type="5" name="Responsiveness" formatstring=""><unSetChoice>2881167</unSetChoice><setChoice>2881166</setChoice></field></auditElement>
UnsetChoice and Set Choice are the columns.
Name=represents the action.
Xml can be parsed using features such as XQuery, or OpenXml.
Here's an example of xquery:
declare #xml as xml = '<auditElement><field id="2881159" type="5" name="Responsiveness"' +
' formatstring=""><unSetChoice>2881167</unSetChoice>' +
'<setChoice>2881166</setChoice></field></auditElement>';
SELECT
Nodes.node.value('(field/#id)[1]', 'INT') AS FieldId,
Nodes.node.value('(field/#name)[1]', 'varchar(50)') AS FieldName,
Nodes.node.value('(field/unSetChoice/text())[1]', 'INT') AS OldValue,
Nodes.node.value('(field/setChoice/text())[1]', 'INT') AS NewValue
FROM
#xml.nodes('//auditElement') AS Nodes(node);
Result:
FieldId FieldName OldValue NewValue
----------- -------------------------------------------------- ----------- -----------
2881159 Responsiveness 2881167 2881166
You can use OUTER APPLY and then break down the parts of the XML field.
The value() method takes XQuery expressions.
For example:
DECLARE #T TABLE (Id int identity(1,1) primary key, XmlCol1 xml);
insert into #T (XmlCol1) values
('<auditElement><field id="2881159" type="5" name="Responsiveness" formatstring=""><unSetChoice>2881167</unSetChoice><setChoice>2881166</setChoice></field></auditElement>'),
('<auditElement><field id="2881160" type="6" name="Responsiveness" ><unSetChoice>2881187</unSetChoice><setChoice>2881188</setChoice></field></auditElement>');
select *
from (
select
Id,
a.field.value('#id', 'int') as xmlid,
a.field.value('(unSetChoice)[1]', 'int') as unSetChoice,
a.field.value('(setChoice)[1]', 'int') as setChoice,
a.field.value('#type', 'int') as type,
a.field.value('#name', 'varchar(max)') as name,
a.field.value('#formatstring', 'varchar(max)') as formatstring
from #T t
outer apply t.XmlCol1.nodes('/auditElement/field') as a(field)
where a.field.value('#id', 'int') > 0 and Id > 0
) q
where name = 'Responsiveness';
Result:
Id xmlid unSetChoice setChoice type name formatstring
1 2881159 2881167 2881166 5 Responsiveness
2 2881160 2881187 2881188 6 Responsiveness NULL

For XML as PIVOT

Thanks for reading.
I need to export data via SQL to XML. But I need the XML format in Row/column and the output must be a Pivot table. I know that it can be done with AS pivot. But I don't know how to use it in the below script
I've already got a fantastic script with the outcome in Row/Column format, but the output must be in pivot
;With CTE
AS
(
SELECT [Name]
,[ColumnA]
,[ColumnB]
,[ColumnC]
FROM Fact_A INNER JOIN Dim_A on
Fact_A.Column_Key = Dim_A.Column_Key
)
select
(
select [Name] AS [#name],
(select [ColumnA] as [column],
null as tmp,
ColumnB as [column],
null as tmp,
ColumnC as [column]
from CTE
where [Name] = t.[Name]
for xml path('row'),type) as [*]
from (select distinct [Name] from CTE)t
for xml path('variable'),root('data')
) as col_xml
the above query needs to be in the same XML format(Row/Clolumn) but then in a Pivot table structure.
The desired outcome:
........CellA...CellB
companyA..4.......3
companyB..0.......4
companyC..1.......2
(whithout the ..............)
The desired outcome in XML:
<data>
<variable name="Name">
<row>
<column></column>
<column>A</column>
<column>B</column>
</row>
<row>
<column>companyA</column>
<column>4</column>
<column>3</column>
</row>
<row>
<column>companyB</column>
<column>0</column>
<column>4</column>
</row>
<row>
<column>companyC</column>
<column>1</column>
<column>2</column>
</row>
</variable>
Is this possible?
Thanks in advance.
Regards,
Bart
;With CTE
AS
(
SELECT [Name]
,[ColumnA]
,[ColumnB]
,[ColumnC]
FROM Fact_A
INNER JOIN Dim_A on
Fact_A.Column_Key = Dim_A.Column_Key
) , pvtClust as
(
select [Name], [ColumnA],
[A], [B]
from CTE
pivot (Sum(ColumnA) for
[Name] in ([A], [B])) pvt
)
select
(
select [Name] AS [#name],
(SELECT '' as [column]
, null as [tmp]
,'A' as [column]
, null as [tmp]
, 'B' as [column]
for xml path ('row'), type) as [*],
(select [Name] as [column],
null as tmp,
ISNULL([A], 0) as [column],
null as tmp,
ISNULL([B], 0) as [column]
from pvtClust
where [Name] = t.[Name]
for xml path('row'),type) as [*]
from (select distinct [Name] from CTE) t
for xml path('variable'),root('data')
) as col_xml
Credits to:
Russel Loski, MCT, MCSE Data Platform/Business Intelligence. Twitter: #sqlmovers; blog: www.sqlmovers.com