please consider this XML:
<Employees>
<Person>
<ID>1000</ID>
<Name>Nima</Name>
<LName>Agha</LName>
</Person>
<Person>
<ID>1001</ID>
<Name>Ligha</Name>
<LName>Ligha</LName>
</Person>
<Person>
<ID>1002</ID>
<Name>Jigha</Name>
<LName>Jigha</LName>
</Person>
<Person>
<ID>1003</ID>
<Name>Aba</Name>
<LName>Aba</LName>
</Person>
</Employees>
I want to write a procedure that get a number and then I insert an element to nth Person element. for example if 1 pass to my procedure I insert an element to first person element.
DECLARE #data XML =
'
<Employees>
<Person>
<ID>1000</ID>
<Name>Nima</Name>
<LName>Agha</LName>
</Person>
<Person>
<ID>1001</ID>
<Name>Ligha</Name>
<LName>Ligha</LName>
</Person>
<Person>
<ID>1002</ID>
<Name>Jigha</Name>
<LName>Jigha</LName>
</Person>
<Person>
<ID>1003</ID>
<Name>Aba</Name>
<LName>Aba</LName>
</Person>
</Employees>
'
DECLARE #offset INT = 2
DECLARE #value VARCHAR(100) = 'newvalue'
SET #data.modify('insert <NewAttribute>{sql:variable("#value")}</NewAttribute> as last into (/Employees/Person)[sql:variable("#offset")][1]')
SELECT #data
DECLARE #AttributeValue NVARCHAr(100) = 'TestValue';
DECLARE #NodeNR INT = 3
DECLARE #XML XML = '<Employees>
<Person>
<ID>1000</ID>
<Name>Nima</Name>
<LName>Agha</LName>
</Person>
<Person>
<ID>1001</ID>
<Name>Ligha</Name>
<LName>Ligha</LName>
</Person>
<Person>
<ID>1002</ID>
<Name>Jigha</Name>
<LName>Jigha</LName>
</Person>
<Person>
<ID>1003</ID>
<Name>Aba</Name>
<LName>Aba</LName>
</Person>
</Employees>';
SET #XML.modify('insert attribute Attribute {sql:variable("#AttributeValue")} into (/Employees/Person[position()=sql:variable("#NodeNr")])[1]')
Try this one -
DECLARE #Param INT = 1000
DECLARE #NodeID INT = 2
DECLARE #XML XML = '
<Employees>
<Person>
<ID>1000</ID>
<Name>Nima</Name>
<LName>Agha</LName>
</Person>
<Person>
<ID>1001</ID>
<Name>Ligha</Name>
<LName>Ligha</LName>
</Person>
<Person>
<ID>1002</ID>
<Name>Jigha</Name>
<LName>Jigha</LName>
</Person>
<Person>
<ID>1003</ID>
<Name>Aba</Name>
<LName>Aba</LName>
</Person>
</Employees>'
DECLARE #SQL NVARCHAR(MAX) = '
DECLARE #XML XML = #XML_Param
DECLARE #Id INT = #Value_Param
SET #XML.modify(''insert attribute Id {sql:variable("#Id")} into (/Employees/Person)[' + CAST(#NodeID AS VARCHAR) + ']'')
SELECT #XML_Output = #XML'
DECLARE #Definition NVARCHAR(500) =
N'#XML_Param XML, #Value_Param INT, #Node_Param INT, #XML_Output XML OUTPUT'
DECLARE #XMLResult XML
EXEC sys.sp_executesql
#SQL
, #Definition
, #XML_Param = #XML
, #Value_Param = #Param
, #Node_Param = 1
, #XML_Output = #XMLResult OUTPUT
SELECT #XMLResult
Related
Given this data:
FName Lname ApartmentNumber
-----------------------------------
David Shumer 1
John Deer 1
Mark Ratz 2
Steven Styer 2
I would like to return it as xml, so I did this:
select * from Table1
for xml raw('person'), root('PeopleInApartment'), elements
And I got this result
<PeopleInApartment>
<Person>
<FName>David</FName>
<LName>Shumer</LName>
<ApartmentNumber>1</ApartmentNumber>
</Person>
<Person>
<FName>John</FName>
<LName>Deer</LName>
<ApartmentNumber>1</ApartmentNumber>
</Person>
<Person>
<FName>Mark</FName>
<LName>Ratz</LName>
<ApartmentNumber>2</ApartmentNumber>
</Person>
<Person>
<FName>Steven</FName>
<LName>Styer</LName>
<ApartmentNumber>2</ApartmentNumber>
</Person>
</PeopleInApartment>
Is it possible to group people by apartment so the result would look like this?:
<Apartments>
<PeopleInApartment>
<Person>
<FName>David</FName>
<LName>Shumer</LName>
<ApartmentNumber>1</ApartmentNumber>
</Person>
<Person>
<FName>John</FName>
<LName>Deer</LName>
<ApartmentNumber>1</ApartmentNumber>
</Person>
</PeopleInApartment>
<PeopleInApartment>
<Person>
<FName>Mark</FName>
<LName>Ratz</LName>
<ApartmentNumber>2</ApartmentNumber>
</Person>
<Person>
<FName>Steven</FName>
<LName>Styer</LName>
<ApartmentNumber>2</ApartmentNumber>
</Person>
</PeopleInApartment>
</Apartments>
Sql solution. Note subquery must depend only on outer columns in the GROUP BY, t1.ApartmentNumber specifically.
select t1.ApartmentNumber
, (select t2.FName, t2.Lname
from Table1 t2
where t2.ApartmentNumber = t1.ApartmentNumber
for xml path('Person'), type
) as PeopleInApartment
from Table1 t1
group by ApartmentNumber
for xml path('Apartment'), root('Apartments'), elements
Returns data apartment - wise
<Apartments>
<Apartment>
<ApartmentNumber>1</ApartmentNumber>
<PeopleInApartment>
<Person>
<FName>David </FName>
<Lname>Shumer</Lname>
</Person>
<Person>
<FName>John </FName>
<Lname>Deer </Lname>
</Person>
</PeopleInApartment>
</Apartment>
<Apartment>
<ApartmentNumber>2</ApartmentNumber>
<PeopleInApartment>
<Person>
<FName>Mark </FName>
<Lname>Ratz </Lname>
</Person>
<Person>
<FName>Steven</FName>
<Lname>Styer </Lname>
</Person>
</PeopleInApartment>
</Apartment>
</Apartments>
Use xml linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication3
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
XElement apartments = new XElement("Apartments");
var groups = doc.Descendants("Person")
.GroupBy(x => (int)x.Element("ApartmentNumber"))
.ToList();
foreach (var group in groups)
{
XElement peopleInApartment = new XElement("PeopleInApartment", group);
apartments.Add(peopleInApartment);
}
}
}
}
Please check Below :
select
(select t2.FName, t2.Lname, t1.ApartmentNumber
from #TEMP t2
where t2.ApartmentNumber = t1.ApartmentNumber
for xml path('Person'), type
) as PeopleInApartment
from #TEMP t1
group by ApartmentNumber
for xml path(''), root ('Apartments')
I am trying to group some elements together under one node. This is my current SQL;
declare #xml xml
set #xml = (
select (
select
'DERIVED' '#type',
m.NuixDerivedFieldName '#name', (
SELECT
NuixFieldType as 'metadata/#type',
NuixFieldName as 'metadata/#name'
from eddsdbo.MetadataMapping m1
where m1.NuixDerivedFieldName = m.NuixDerivedFieldName
for xml path ('first-non-blank'), type
)
from (select distinct NuixDerivedFieldName from eddsdbo.MetadataMapping) m
for xml path ('metadata'))
)
;WITH XMLNAMESPACES(DEFAULT 'http://nuix.com/fbi/metadata-profile')
select #xml for XML PATH ('metadata-list'), ROOT ('metadata-profile')
Which gives me the following output;
<metadata-profile xmlns="http://nuix.com/fbi/metadata-profile">
<metadata-list>
<metadata type="DERIVED" name="Barcode" xmlns="">
<first-non-blank>
<metadata type="CUSTOM" name="Barcode" />
</first-non-blank>
<first-non-blank>
<metadata type="EVIDENCE" name="Barcode" />
</first-non-blank>
</metadata>
I want to group together elements together which have the same 'name' attribute of the metadata element under the <first-non-blank> element.
The desired output should be;
<metadata-profile xmlns="http://nuix.com/fbi/metadata-profile">
<metadata-list>
<metadata type="DERIVED" name="Barcode" xmlns="">
<first-non-blank>
<metadata type="CUSTOM" name="Barcode" />
<metadata type="EVIDENCE" name="Barcode" />
</first-non-blank>
</metadata>
...
My database looks something like this;
NuixFieldName NuixFieldType NuixDerivedFieldName
------------------------------ ------------------------------ ------------------------------
_EmailEntryID PROPERTY EmailEntryID
Audited Audited Audited
Author PROPERTY Author
Barcode CUSTOM Barcode
Barcode EVIDENCE Barcode
I would also like to remove the xlmns namespace identifier from the metadata elements.
Thanks in advance!
You could try this
DECLARE #SampleData AS TABLE
(
NuixFieldName varchar(20),
NuixFieldType varchar(20),
NuixDerivedFieldName varchar(20)
)
INSERT INTO #SampleData
VALUES
('_EmailEntryID','PROPERTY','EmailEntryID'),
('Audited', 'Audited ','Audited'),
('Author ', 'PROPERTY','Author '),
('Barcode', 'CUSTOM ','Barcode'),
('Barcode', 'EVIDENCE','Barcode')
DECLARE #xml XML
SET #xml = (
SELECT
-- sd.NuixDerivedFieldName AS [#name],
'DERIVED' AS [#type],
sd.NuixDerivedFieldName AS [#name],
(
SELECT
sd2.NuixFieldType as '#type',
sd2.NuixFieldName as '#name'
FROM #SampleData sd2 WHERE sd2.NuixDerivedFieldName = sd.NuixDerivedFieldName
FOR XML PATH ('metadata'),ROOT('first-non-blank'), TYPE
)
FROM (select DISTINCT sd.NuixDerivedFieldName from #SampleData sd ) sd
FOR XML PATH('metadata'), ROOT('metadata-list'),TYPE
)
;WITH XMLNAMESPACES(DEFAULT 'http://nuix.com/fbi/metadata-profile')
SELECT #xml FOR XML PATH (''),ROOT('metadata-profile')
return:
<metadata-profile xmlns="http://nuix.com/fbi/metadata-profile">
<metadata-list>
<metadata type="DERIVED" name="Audited">
<first-non-blank>
<metadata type="Audited " name="Audited" />
</first-non-blank>
</metadata>
<metadata type="DERIVED" name="Author ">
<first-non-blank>
<metadata type="PROPERTY" name="Author " />
</first-non-blank>
</metadata>
<metadata type="DERIVED" name="Barcode">
<first-non-blank>
<metadata type="CUSTOM " name="Barcode" />
<metadata type="EVIDENCE" name="Barcode" />
</first-non-blank>
</metadata>
<metadata type="DERIVED" name="EmailEntryID">
<first-non-blank>
<metadata type="PROPERTY" name="_EmailEntryID" />
</first-non-blank>
</metadata>
</metadata-list>
</metadata-profile>
I need to create xml files to migrate a huge amount of data from one database to another database.
How to get result xsd format as below from ms sql script query?
Please share if you have any idea.
The xml file format is below:
<Batch>
<retail:customer xmlns:core="http://www.bactor.com/core" xmlns:retail=""http://www.bactor.com/retail" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<retail:addresses>
<retail:address>
<retail:country>GB</retail:country>
<retail:countryCodeId></retail:countryCodeId>
<retail:isPreferred>true</retail:isPreferred>
<retail:isActive>true</retail:isActive>
<retail:typeId>PERSONAL_ADDRESS</retail:typeId>
<retail:postCode>2344</retail:postCode>
<retail:street1>1234214</retail:street1>
<retail:isTemplate>false</retail:isTemplate>
<retail:referenceId></retail:referenceId>
<retail:addressReferenceId>0727-:83f5bd9f331:e8e438a1:fa34668911272008</retail:addressReferenceId>
</retail:address>
</retail:addresses>
<retail:contactMethod></retail:contactMethod>
<retail:contactable>false</retail:contactable>
<retail:maritalStatus></retail:maritalStatus>
<retail:nationality></retail:nationality>
<retail:noChildren>0</retail:noChildren>
<retail:customerNumber>1</retail:customerNumber>
<retail:emailAddresses>
<retail:emailAddress>alice#wonderland.hearts</retail:emailAddress>
<retail:preferred>true</retail:preferred>
<retail:restrictedReason></retail:restrictedReason>
<retail:status></retail:status>
<retail:typeId>PERSONAL_EMAIL</retail:typeId>
<retail:referenceId></retail:referenceId>
<retail:active>false</retail:active>
</retail:emailAddresses>
<retail:phoneNumbers>
<retail:countryCode></retail:countryCode>
<retail:number>11222445566</retail:number>
<retail:preferred>true</retail:preferred>
<retail:restrictedReason></retail:restrictedReason>
<retail:status></retail:status>
<retail:typeId>LANDLINE</retail:typeId>
<retail:referenceId></retail:referenceId>
<retail:active>true</retail:active>
<retail:phoneNumberReferenceId>e437-:83f5bd9f331:e8e438a1:fa34668911272008</retail:phoneNumberReferenceId>
</retail:phoneNumbers>
<retail:customerName>
<retail:surname>AppleGate</retail:surname>
<retail:forename>Alice</retail:forename>
<retail:title>Mrs</retail:title>
<retail:sex>FEMALE</retail:sex>
<retail:dateOfBirth>2012-09-12T00:00:00+01:00</retail:dateOfBirth>
</retail:customerName>
<retail:businessContactMethod></retail:businessContactMethod>
<retail:preferredContactTime></retail:preferredContactTime>
<retail:allowInternalMarketing>true</retail:allowInternalMarketing>
<retail:allowExternalMarketing>true</retail:allowExternalMarketing>
<retail:employeeKey></retail:employeeKey>
<retail:customerType>RETAIL</retail:customerType>
<retail:organisation></retail:organisation>
<retail:taxIdentification></retail:taxIdentification>
<retail:companyNumber></retail:companyNumber>
<retail:createdBy></retail:createdBy>
<retail:createdAt></retail:createdAt>
<retail:status>New</retail:status>
<retail:source></retail:source>
</retail:customer>
<retail:customer xmlns:core="http://www.enactor.com/core" xmlns:retail="http://www.enactor.com/retail" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<retail:addresses>
<retail:address>
<retail:country>GB</retail:country>
<retail:countryCodeId></retail:countryCodeId>
<retail:isPreferred>true</retail:isPreferred>
<retail:isActive>true</retail:isActive>
<retail:typeId>PERSONAL_ADDRESS</retail:typeId>
<retail:postCode>2344</retail:postCode>
<retail:street1>1234214</retail:street1>
<retail:isTemplate>false</retail:isTemplate>
<retail:referenceId></retail:referenceId>
<retail:addressReferenceId>0727-:83f5bd9f331:e8e438a1:fa34668911272008</retail:addressReferenceId>
</retail:address>
</retail:addresses>
<retail:contactMethod></retail:contactMethod>
<retail:contactable>false</retail:contactable>
<retail:maritalStatus></retail:maritalStatus>
<retail:nationality></retail:nationality>
<retail:noChildren>0</retail:noChildren>
<retail:customerNumber>1</retail:customerNumber>
<retail:emailAddresses>
<retail:emailAddress>alice#wonderland.hearts</retail:emailAddress>
<retail:preferred>true</retail:preferred>
<retail:restrictedReason></retail:restrictedReason>
<retail:status></retail:status>
<retail:typeId>PERSONAL_EMAIL</retail:typeId>
<retail:referenceId></retail:referenceId>
<retail:active>false</retail:active>
</retail:emailAddresses>
<retail:phoneNumbers>
<retail:countryCode></retail:countryCode>
<retail:number>11222445566</retail:number>
<retail:preferred>true</retail:preferred>
<retail:restrictedReason></retail:restrictedReason>
<retail:status></retail:status>
<retail:typeId>LANDLINE</retail:typeId>
<retail:referenceId></retail:referenceId>
<retail:active>true</retail:active>
<retail:phoneNumberReferenceId>e437-:83f5bd9f331:e8e438a1:fa34668911272008</retail:phoneNumberReferenceId>
</retail:phoneNumbers>
<retail:customerName>
<retail:surname>AppleGate</retail:surname>
<retail:forename>Alice</retail:forename>
<retail:title>Mrs</retail:title>
<retail:sex>FEMALE</retail:sex>
<retail:dateOfBirth>2012-09-12T00:00:00+01:00</retail:dateOfBirth>
</retail:customerName>
<retail:businessContactMethod></retail:businessContactMethod>
<retail:preferredContactTime></retail:preferredContactTime>
<retail:allowInternalMarketing>true</retail:allowInternalMarketing>
<retail:allowExternalMarketing>true</retail:allowExternalMarketing>
<retail:employeeKey></retail:employeeKey>
<retail:customerType>RETAIL</retail:customerType>
<retail:organisation></retail:organisation>
<retail:taxIdentification></retail:taxIdentification>
<retail:companyNumber></retail:companyNumber>
<retail:createdBy></retail:createdBy>
<retail:createdAt></retail:createdAt>
<retail:status>New</retail:status>
<retail:source></retail:source>
</retail:customer>
</Batch>
I am also trying with the below a pieces of sql script. but it is not working.
WITH XMLNAMESPACES ('http://www.enactor.com/retail' as ns1)
SELECT top 100 [id]
,[Title]
,[First_Name]
, RowNum = Row_NUMBER() OVER (Order by id)
FROM [Firinne].[dbo].[Contact] as Customer
For XML PATH('retail:Customer')
Try this:
DECLARE #xml XML
;WITH XMLNAMESPACES('http://www.w3.org/2001/XMLSchema-instance' AS xsi, 'http://www.bactor.com/retail' AS retail, 'http://www.bactor.com/core' AS core)
SELECT #xml = (SELECT
[retail:Customer].id AS [retail:id],
[retail:Customer].contactMethod AS [retail:contactMethod],
[retail:Customer].contactable AS [retail:contactable],
[retail:address].emailAddress AS [retail:emailAddress],
[retail:address].typeId AS [retail:typeId]
FROM dbo.Customers AS [retail:Customer]
JOIN dbo.emailAddresses AS [retail:address] ON [retail:Customer].id = [retail:address].customerID
FOR XML AUTO, ELEMENTS)
SET #xml = '<Batch>' + CAST(#xml AS NVARCHAR(max)) + '</Batch>'
SELECT #xml
Output:
<Batch>
<retail:Customer xmlns:core="http://www.bactor.com/core" xmlns:retail="http://www.bactor.com/retail" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<retail:id>1</retail:id>
<retail:contactMethod>1</retail:contactMethod>
<retail:contactable>1</retail:contactable>
<retail:address>
<retail:emailAddress>some#some.some</retail:emailAddress>
<retail:typeId>1</retail:typeId>
</retail:address>
<retail:address>
<retail:emailAddress>some#some.some</retail:emailAddress>
<retail:typeId>2</retail:typeId>
</retail:address>
</retail:Customer>
<retail:Customer xmlns:core="http://www.bactor.com/core" xmlns:retail="http://www.bactor.com/retail" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<retail:id>2</retail:id>
<retail:contactMethod>1</retail:contactMethod>
<retail:contactable>0</retail:contactable>
<retail:address>
<retail:emailAddress>some#some.some</retail:emailAddress>
<retail:typeId>3</retail:typeId>
</retail:address>
</retail:Customer>
</Batch>
EDIT:
You can do it like:
DECLARE #xml XML
;WITH XMLNAMESPACES('http://www.w3.org/2001/XMLSchema-instance' AS xsi, 'http://www.bactor.com/retail' AS retail, 'http://www.bactor.com/core' AS core)
SELECT #xml = (SELECT
[retail:Customer].id AS [retail:id],
[retail:Customer].contactMethod AS [retail:contactMethod],
[retail:Customer].contactable AS [retail:contactable],
(SELECT
[retail:address].emailAddress ,
[retail:address].typeId
FROM dbo.emailAddresses AS [retail:address] WHERE [retail:Customer].id = [retail:address].customerID
FOR XML AUTO, TYPE, ELEMENTS, ROOT('retail:Addresses')
)
FROM dbo.Customers AS [retail:Customer]
FOR XML AUTO, ELEMENTS)
SET #xml = '<Batch>' + CAST(#xml AS NVARCHAR(max)) + '</Batch>'
SELECT #xml
But namespaces are added to all child:
<Batch>
<retail:Customer xmlns:core="http://www.bactor.com/core" xmlns:retail="http://www.bactor.com/retail" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<retail:id>1</retail:id>
<retail:contactMethod>1</retail:contactMethod>
<retail:contactable>1</retail:contactable>
<retail:Addresses xmlns:core="http://www.bactor.com/core" xmlns:retail="http://www.bactor.com/retail" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<retail:address>
<emailAddress>some#some.some</emailAddress>
<typeId>1</typeId>
</retail:address>
<retail:address>
<emailAddress>some#some.some</emailAddress>
<typeId>2</typeId>
</retail:address>
</retail:Addresses>
</retail:Customer>
<retail:Customer xmlns:core="http://www.bactor.com/core" xmlns:retail="http://www.bactor.com/retail" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<retail:id>2</retail:id>
<retail:contactMethod>1</retail:contactMethod>
<retail:contactable>0</retail:contactable>
<retail:Addresses xmlns:core="http://www.bactor.com/core" xmlns:retail="http://www.bactor.com/retail" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<retail:address>
<emailAddress>some#some.some</emailAddress>
<typeId>3</typeId>
</retail:address>
</retail:Addresses>
</retail:Customer>
</Batch>
It is a known issue, and you can see details here:
https://connect.microsoft.com/SQLServer/feedback/details/265956/suppress-namespace-attributes-in-nested-select-for-xml-statements
Additional namespaces doesn't do any harm but increasing size of generated xml document.
I have a huge XML, with over 150 element and attributes. I need to populate only a handful of them ( 5 or 6) elements with data from a SQL server 2008 tables. This created xml need to be passed to a webservice ( to ESB) and this has to happen on a daily schedule.
I think, it does not make sense to use XML Path here to create the XML and use SSIS. Can anyone suggest an approach?
This is the sample XML. I need just the names, address and a few ids populated
<?xml version="1.0" encoding="UTF-8"?>
<Customer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Customer.xsd">
<CustomerData>
<StoreID></StoreID>
<FirstName></FirstName>
<LastName></LastName>
<Gender></Gender>
<BirthMonth></BirthMonth>
<BirthYear></BirthYear>
<BirthDay></BirthDay>
<IsEmployee></IsEmployee>
<customerID></customerID>
<EmailAddress></EmailAddress>
<PhoneNumber></PhoneNumber>
<EmailSignUp></EmailSignUp>
<CatalogSignup></CatalogSignup>
<Addresses>
<BillingAddress>
<Address1></Address1>
<Address2></Address2>
<Address3></Address3>
<City></City>
<State></State>
<ZipCode></ZipCode>
<Fax1></Fax1>
</BillingAddress>
<CatalogSignupAddress>
<Address1></Address1>
<Address2></Address2>
<Address3></Address3>
<City></City>
<State></State>
<ZipCode></ZipCode>
<Fax1></Fax1>
</CatalogSignupAddress>
<StoredAddresses>
<StoredAddress>
<Address1></Address1>
<Address2></Address2>
<Address3></Address3>
<City></City>
<State></State>
<ZipCode></ZipCode>
<Fax1></Fax1>
</StoredAddress>
<StoredAddress>
<Address1></Address1>
<Address2></Address2>
<Address3></Address3>
<City></City>
<State></State>
<ZipCode></ZipCode>
<Fax1></Fax1>
</StoredAddress>
</StoredAddresses>
</Addresses>
<Hobbies_Enjoys>
<Hobby></Hobby>
<Enjoy></Enjoy>
</Hobbies_Enjoys>
<FavoriteFossilProducts>
<ProductType></ProductType>
<ProductType></ProductType>
</FavoriteFossilProducts>
<AgeRange></AgeRange>
<PreferredEmailFormat></PreferredEmailFormat>
<SavedCreditCards>
<CreditCard>
<AcctNum></AcctNum>
<ExpiryDate></ExpiryDate>
</CreditCard>
<CreditCard>
<AcctNum></AcctNum>
<ExpiryDate></ExpiryDate>
</CreditCard>
</SavedCreditCards>
<PurchasedProductList>
<SKU></SKU>
<SKU></SKU>
</PurchasedProductList>
<OrderHistory>
<Orders>
<Order>
<Number></Number>
<TotalAmount></TotalAmount>
<Promotion></Promotion>
<TimePlaced></TimePlaced>
</Order>
<Order>
<Number></Number>
<TotalAmount></TotalAmount>
<Promotion></Promotion>
<TimePlaced></TimePlaced>
</Order>
</Orders>
</OrderHistory>
<WishLists>
<WishList>
<Name></Name>
<Description></Description>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
<IsDefault></IsDefault>
<Items>
<Item>
<Quantity></Quantity>
<PartNumber></PartNumber>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
</Item>
<Item>
<Quantity></Quantity>
<PartNumber></PartNumber>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
</Item>
</Items>
</WishList>
<WishList>
<Name></Name>
<Description></Description>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
<IsDefault></IsDefault>
<Items>
<Item>
<Quantity></Quantity>
<PartNumber></PartNumber>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
</Item>
<Item>
<Quantity></Quantity>
<PartNumber></PartNumber>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
</Item>
</Items>
</WishList>
</WishLists>
</CustomerData>
<CustomerData>
</CustomerData>
</Customer>
One approach is to take an empty version of your XML document and assign it to an NVARCHAR(MAX) variable. For each node or parameter you wish to populate, put a "token" and use the replace function to populate the value. For example:
DECLARE #xml NVARCHAR(MAX)
SET #xml = N'<Company name="~company_name~">
<Department name="~dept_name~">
<Employee name="~employee_name~" title="~employee_title~" />
</Department>
</Company>'
SET #xml = REPLACE(#xml,N'~company_name~','Microsoft')
SET #xml = REPLACE(#xml,N'~dept_name~','Executive')
SET #xml = REPLACE(#xml,N'~employee_name~','Satya Nadella')
SET #xml = REPLACE(#xml,N'~employee_title~','CEO')
SELECT CAST(#xml AS XML)
Here's a more traditional approach. You'll need an arbitrary value in the cells you wish to update:
DECLARE #example_data TABLE
(FirstName VARCHAR(255) NOT NULL,
LastName VARCHAR(255) NOT NULL,
Gender CHAR(1) NOT NULL,
City VARCHAR(255) NOT NULL,
[State] CHAR(2) NOT NULL)
INSERT INTO #example_data
( FirstName , LastName , Gender , City , [State])
VALUES ( 'Satya' , -- FirstName - varchar(255)
'Nadella' , -- LastName - varchar(255)
'M' , -- Gender - char(1)
'Redmond' , -- City - varchar(255)
'WA' -- State - char(2)
)
INSERT INTO #example_data
( FirstName , LastName , Gender , City , [State])
VALUES ( 'Larry' , -- FirstName - varchar(255)
'Ellison' , -- LastName - varchar(255)
'M' , -- Gender - char(1)
'Woodside' , -- City - varchar(255)
'CA' -- State - char(2)
)
DECLARE
#customer_xml XML,
#xml XML,
#temp NVARCHAR(255),
#FirstName VARCHAR(255),
#LastName VARCHAR(255),
#Gender CHAR(1),
#City VARCHAR(255),
#State CHAR(2)
SET #customer_xml = '<?xml version="1.0" encoding="UTF-8"?>
<Customer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Customer.xsd">
<CustomerData>
<StoreID></StoreID>
<FirstName>a</FirstName>
<LastName>b</LastName>
<Gender>c</Gender>
<BirthMonth></BirthMonth>
<BirthYear></BirthYear>
<BirthDay></BirthDay>
<IsEmployee></IsEmployee>
<customerID></customerID>
<EmailAddress></EmailAddress>
<PhoneNumber></PhoneNumber>
<EmailSignUp></EmailSignUp>
<CatalogSignup></CatalogSignup>
<Addresses>
<BillingAddress>
<Address1></Address1>
<Address2></Address2>
<Address3></Address3>
<City>d</City>
<State>e</State>
<ZipCode></ZipCode>
<Fax1></Fax1>
</BillingAddress>
<CatalogSignupAddress>
<Address1></Address1>
<Address2></Address2>
<Address3></Address3>
<City></City>
<State></State>
<ZipCode></ZipCode>
<Fax1></Fax1>
</CatalogSignupAddress>
<StoredAddresses>
<StoredAddress>
<Address1></Address1>
<Address2></Address2>
<Address3></Address3>
<City></City>
<State></State>
<ZipCode></ZipCode>
<Fax1></Fax1>
</StoredAddress>
<StoredAddress>
<Address1></Address1>
<Address2></Address2>
<Address3></Address3>
<City></City>
<State></State>
<ZipCode></ZipCode>
<Fax1></Fax1>
</StoredAddress>
</StoredAddresses>
</Addresses>
<Hobbies_Enjoys>
<Hobby></Hobby>
<Enjoy></Enjoy>
</Hobbies_Enjoys>
<FavoriteFossilProducts>
<ProductType></ProductType>
<ProductType></ProductType>
</FavoriteFossilProducts>
<AgeRange></AgeRange>
<PreferredEmailFormat></PreferredEmailFormat>
<SavedCreditCards>
<CreditCard>
<AcctNum></AcctNum>
<ExpiryDate></ExpiryDate>
</CreditCard>
<CreditCard>
<AcctNum></AcctNum>
<ExpiryDate></ExpiryDate>
</CreditCard>
</SavedCreditCards>
<PurchasedProductList>
<SKU></SKU>
<SKU></SKU>
</PurchasedProductList>
<OrderHistory>
<Orders>
<Order>
<Number></Number>
<TotalAmount></TotalAmount>
<Promotion></Promotion>
<TimePlaced></TimePlaced>
</Order>
<Order>
<Number></Number>
<TotalAmount></TotalAmount>
<Promotion></Promotion>
<TimePlaced></TimePlaced>
</Order>
</Orders>
</OrderHistory>
<WishLists>
<WishList>
<Name></Name>
<Description></Description>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
<IsDefault></IsDefault>
<Items>
<Item>
<Quantity></Quantity>
<PartNumber></PartNumber>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
</Item>
<Item>
<Quantity></Quantity>
<PartNumber></PartNumber>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
</Item>
</Items>
</WishList>
<WishList>
<Name></Name>
<Description></Description>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
<IsDefault></IsDefault>
<Items>
<Item>
<Quantity></Quantity>
<PartNumber></PartNumber>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
</Item>
<Item>
<Quantity></Quantity>
<PartNumber></PartNumber>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
</Item>
</Items>
</WishList>
</WishLists>
</CustomerData>
</Customer>'
DECLARE xml_cursor CURSOR FOR
SELECT FirstName , LastName , Gender , City , [State]
FROM #example_data
OPEN xml_cursor
FETCH NEXT FROM xml_cursor into #FirstName, #LastName, #Gender, #City, #State
WHILE ##fetch_status = 0
BEGIN
SET #xml = #customer_xml
SET #xml.modify('
replace value of (/Customer/CustomerData/FirstName[1]/text())[1]
with sql:variable("#FirstName")
')
SET #xml.modify('
replace value of (/Customer/CustomerData/LastName[1]/text())[1]
with sql:variable("#LastName")
')
SET #xml.modify('
replace value of (/Customer/CustomerData/Gender[1]/text())[1]
with sql:variable("#Gender")
')
SET #xml.modify('
replace value of (/Customer/CustomerData/Addresses/BillingAddress/City[1]/text())[1]
with sql:variable("#City")
')
SET #xml.modify('
replace value of (/Customer/CustomerData/Addresses/BillingAddress/State[1]/text())[1]
with sql:variable("#State")
')
select #xml
FETCH NEXT FROM xml_cursor into #FirstName, #LastName, #Gender, #City, #State
END
This approach does not require a value in the nodes to be updated. It simply inserts a new node, then deletes the old node:
DECLARE #example_data TABLE
(FirstName VARCHAR(255) NOT NULL,
LastName VARCHAR(255) NOT NULL,
Gender CHAR(1) NOT NULL,
City VARCHAR(255) NOT NULL,
[State] CHAR(2) NOT NULL)
INSERT INTO #example_data
( FirstName , LastName , Gender , City , [State])
VALUES ( 'Satya' , -- FirstName - varchar(255)
'Nadella' , -- LastName - varchar(255)
'M' , -- Gender - char(1)
'Redmond' , -- City - varchar(255)
'WA' -- State - char(2)
)
INSERT INTO #example_data
( FirstName , LastName , Gender , City , [State])
VALUES ( 'Larry' , -- FirstName - varchar(255)
'Ellison' , -- LastName - varchar(255)
'M' , -- Gender - char(1)
'Woodside' , -- City - varchar(255)
'CA' -- State - char(2)
)
DECLARE
#customer_xml XML,
#xml XML,
#temp NVARCHAR(255),
#FirstName VARCHAR(255),
#LastName VARCHAR(255),
#Gender CHAR(1),
#City VARCHAR(255),
#State CHAR(2)
SET #customer_xml = '<?xml version="1.0" encoding="UTF-8"?>
<Customer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Customer.xsd">
<CustomerData>
<StoreID></StoreID>
<FirstName></FirstName>
<LastName></LastName>
<Gender></Gender>
<BirthMonth></BirthMonth>
<BirthYear></BirthYear>
<BirthDay></BirthDay>
<IsEmployee></IsEmployee>
<customerID></customerID>
<EmailAddress></EmailAddress>
<PhoneNumber></PhoneNumber>
<EmailSignUp></EmailSignUp>
<CatalogSignup></CatalogSignup>
<Addresses>
<BillingAddress>
<Address1></Address1>
<Address2></Address2>
<Address3></Address3>
<City></City>
<State></State>
<ZipCode></ZipCode>
<Fax1></Fax1>
</BillingAddress>
<CatalogSignupAddress>
<Address1></Address1>
<Address2></Address2>
<Address3></Address3>
<City></City>
<State></State>
<ZipCode></ZipCode>
<Fax1></Fax1>
</CatalogSignupAddress>
<StoredAddresses>
<StoredAddress>
<Address1></Address1>
<Address2></Address2>
<Address3></Address3>
<City></City>
<State></State>
<ZipCode></ZipCode>
<Fax1></Fax1>
</StoredAddress>
<StoredAddress>
<Address1></Address1>
<Address2></Address2>
<Address3></Address3>
<City></City>
<State></State>
<ZipCode></ZipCode>
<Fax1></Fax1>
</StoredAddress>
</StoredAddresses>
</Addresses>
<Hobbies_Enjoys>
<Hobby></Hobby>
<Enjoy></Enjoy>
</Hobbies_Enjoys>
<FavoriteFossilProducts>
<ProductType></ProductType>
<ProductType></ProductType>
</FavoriteFossilProducts>
<AgeRange></AgeRange>
<PreferredEmailFormat></PreferredEmailFormat>
<SavedCreditCards>
<CreditCard>
<AcctNum></AcctNum>
<ExpiryDate></ExpiryDate>
</CreditCard>
<CreditCard>
<AcctNum></AcctNum>
<ExpiryDate></ExpiryDate>
</CreditCard>
</SavedCreditCards>
<PurchasedProductList>
<SKU></SKU>
<SKU></SKU>
</PurchasedProductList>
<OrderHistory>
<Orders>
<Order>
<Number></Number>
<TotalAmount></TotalAmount>
<Promotion></Promotion>
<TimePlaced></TimePlaced>
</Order>
<Order>
<Number></Number>
<TotalAmount></TotalAmount>
<Promotion></Promotion>
<TimePlaced></TimePlaced>
</Order>
</Orders>
</OrderHistory>
<WishLists>
<WishList>
<Name></Name>
<Description></Description>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
<IsDefault></IsDefault>
<Items>
<Item>
<Quantity></Quantity>
<PartNumber></PartNumber>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
</Item>
<Item>
<Quantity></Quantity>
<PartNumber></PartNumber>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
</Item>
</Items>
</WishList>
<WishList>
<Name></Name>
<Description></Description>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
<IsDefault></IsDefault>
<Items>
<Item>
<Quantity></Quantity>
<PartNumber></PartNumber>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
</Item>
<Item>
<Quantity></Quantity>
<PartNumber></PartNumber>
<DateCreated></DateCreated>
<LastUpdate></LastUpdate>
</Item>
</Items>
</WishList>
</WishLists>
</CustomerData>
</Customer>'
DECLARE xml_cursor CURSOR FOR
SELECT FirstName , LastName , Gender , City , [State]
FROM #example_data
OPEN xml_cursor
FETCH NEXT FROM xml_cursor into #FirstName, #LastName, #Gender, #City, #State
WHILE ##fetch_status = 0
BEGIN
SET #xml = #customer_xml
SET #xml.modify('
insert <FirstName>{ xs:string(sql:variable("#FirstName")) }</FirstName>
before (/Customer/CustomerData/FirstName)[1]
')
SET #xml.modify('
delete /Customer/CustomerData/FirstName[2]
')
SET #xml.modify('
insert <LastName>{ xs:string(sql:variable("#LastName")) }</LastName>
before (/Customer/CustomerData/LastName)[1]
')
SET #xml.modify('
delete /Customer/CustomerData/LastName[2]
')
SET #xml.modify('
insert <Gender>{ xs:string(sql:variable("#Gender")) }</Gender>
before (/Customer/CustomerData/Gender)[1]
')
SET #xml.modify('
delete /Customer/CustomerData/Gender[2]
')
SET #xml.modify('
insert <City>{ xs:string(sql:variable("#City")) }</City>
before (/Customer/CustomerData/Addresses/BillingAddress/City)[1]
')
SET #xml.modify('
delete /Customer/CustomerData/Addresses/BillingAddress/City[2]
')
SET #xml.modify('
insert <State>{ xs:string(sql:variable("#State")) }</State>
before (/Customer/CustomerData/Addresses/BillingAddress/State)[1]
')
SET #xml.modify('
delete /Customer/CustomerData/Addresses/BillingAddress/State[2]
')
select #xml
FETCH NEXT FROM xml_cursor into #FirstName, #LastName, #Gender, #City, #State
END
you can also use FLWOR which will allow you to generate the xml in one go by using a template and adding data only to the elements you want.
You won't need to create tables or stored procedures. For example:
declare #x xml
set #x=(select FirstName, LastName from kc_consumer for xml path('CustomerData'))
SELECT #x.query('
for $a in /CustomerData
return
<CustomerData>
<StoreID></StoreID>
<FirstName>{data($a/FirstName)}</FirstName>
<LastName>{data($a/LastName)}</LastName>
<Gender></Gender>
<BirthMonth></BirthMonth>
<BirthYear></BirthYear>
<BirthDay></BirthDay>
<IsEmployee></IsEmployee>
<customerID></customerID>
</CustomerData>
')
I'm just including a few nodes for readability, you just need to paste the rest of them.
Please consider this XML:
<Employees>
<Person>
<ID>1000</ID>
<Name>Nima</Name>
<LName>Agha</LName>
</Person>
<Person>
<ID>1001</ID>
<Name>Ligha</Name>
<LName>Ligha</LName>
</Person>
<Person>
<ID>1002</ID>
<Name>Jigha</Name>
<LName>Jigha</LName>
</Person>
<Person>
<ID>1003</ID>
<Name>Aba</Name>
<LName>Aba</LName>
</Person>
</Employees>
I want to write a function that gets a number, and then I get nth Person element, and Name. For example if 0 pass to my function I return Aba, if 1 pass to my function I return Jigha.
This should work. Set the value of the #index variable as the number of the record to find, relative to the end of the list:
declare #index int = 1
declare #xml xml = '<Employees>
<Person>
<ID>1000</ID>
<Name>Nima</Name>
<LName>Agha</LName>
</Person>
<Person>
<ID>1001</ID>
<Name>Ligha</Name>
<LName>Ligha</LName>
</Person>
<Person>
<ID>1002</ID>
<Name>Jigha</Name>
<LName>Jigha</LName>
</Person>
<Person>
<ID>1003</ID>
<Name>Aba</Name>
<LName>Aba</LName>
</Person>
</Employees>'
select t2.person.value('(Name/text())[1]','varchar(50)')
from #xml.nodes('Employees/Person[position()=(last()-sql:variable("#index"))]') as t2(person)