SQL Server Create New Line in XML - sql-server

I am trying to figure out how I can insert a new line between fields in SQL Server 2008.
Current XML:
<products>
<product>
<ProductID>1</ProductID>
<ProductName>A.1</ProductName>
</product>
<product>
<ProductID>2</ProductID>
<ProductName>B.1</ProductName>
</product>
</products>
Desired XML:
<products>
<product>
<ProductID>1</ProductID>
<ProductName>A.1</ProductName>
</product>
<product>
<ProductID>2</ProductID>
<ProductName>B.1</ProductName>
</product>
</products>
Any ideas how I can inject Newline/carriage return in the XML output?
Any thoughts would be greatly appreciated.
Thanks,
S

Simple. Take the output, insert the lines. That is AFTER sql server.

Related

Best ETL tool for converting XML to a table

I need to convert >500 XML's to tables that I can query. I have the XSD that I use to verify the structure. I was considering using notepad++ to structure the files. Is that a good idea, if not what is better? The end goal is either flatfiles with the same columns or directly to SQL
Example #1 XML
(...)
<Customer>
<CustomerID>1</CustomerID>
<Address>
<Street>John Street</Street>
<Number>6</Number>
<Apartment>68</Apartment>
<City>New York</City>
<Zip>10068</Zip>
</Address>
<Firstname>John</Firstname>
<LastName>Doe<LastName/>
</Customer>
(...)
Example #2 XML
(...)
<Customer>
<CustomerID>2</CustomerID>
<Address>
<Street>Wall Street</Street>
<City>New York</City>
</Address>
<Firstname>James Smith</Firstname>
</Customer>
(...)
Example #3 XML
(...)
<n1:Customer>
<n1:CustomerID>3</n1:CustomerID>
<n1:Address>
<n1:Apartment>32</n1:Apartment>
<n1:City>Chicago</n1:City>
</n1:Address>
</n1:Customer>
(...)

Convert XML from one format to another

I have this below xml data which is stored in a table.
The XML Structure I have
<Response>
<Question ID="1">
<Value ID="1">I want a completely natural childbirth - no medical interventions for me</Value>
<Value ID="2">no medical interventions for me</Value>
</Question>
</Response>
I need to convert this XML to a slightly different format, like the below one.
The XML Structure I need
<Response>
<Question ID="1">
<SelectedChoices>
<Choice>
<ID>1</ID>
</Choice>
<Choice>
<ID>2</ID>
</Choice>
</SelectedChoices>
</Question>
</Response>
Here the "Value" is changed to "Choice" and "ID" attribute of "Value" element is changed to an element.
I know this can be done in other ways, like using an XSLT. But it will be much more helpful if can accomplish with SQL itself.
Can someone help me to convert this using SQL?
Use this variable to test the statements
DECLARE #xml XML=
N'<Response>
<Question ID="1">
<Value ID="1">I want a completely natural childbirth - no medical interventions for me</Value>
<Value ID="2">no medical interventions for me</Value>
</Question>
</Response>';
This can be done with FLWOR-XQuery:
The query will re-build the XML out of itself... Very similar to XSLT...
SELECT #xml.query(
N'
<Response>
{
for $q in /Response/Question
return
<Question ID="{$q/#ID}">
<SelectedChoices>
{
for $v in $q/Value
return <Choice><ID>{string($v/#ID)}</ID></Choice>
}
</SelectedChoices>
</Question>
}
</Response>
'
);
Another approach: Shredding and re-build
You'd reach the same with this, but I'd prefere the first...
WITH Shredded AS
(
SELECT q.value('#ID','int') AS qID
,v.value('#ID','int') AS vID
FROM #xml.nodes('/Response/Question') AS A(q)
OUTER APPLY q.nodes('Value') AS B(v)
)
SELECT t1.qID AS [#ID]
,(
SELECT t2.vID AS ID
FROM Shredded AS t2
WHERE t1.qID=t2.qID
FOR XML PATH('Choice'),ROOT('SelectedChoices'),TYPE
) AS [node()]
FROM Shredded AS t1
GROUP BY t1.qID
FOR XML PATH('Question'),ROOT('Response')

Call a procedure or function in Oracle DB with return = array of UDT from WSO2 DSS

I follow this post[1] as a guide to build an example of query an array of UDT in WSO2 DSS. In the post just query an UDT, my config try to query an UDT array.
I created this in my DB, a dummy PROCEDURE to try this:
create or replace
TYPE "LIST_CUSTOMERS" IS TABLE OF customer_t
CREATE OR REPLACE
PROCEDURE getCustomer2(listcust OUT list_customers) IS
cust customer_t;
cust2 customer_t;
BEGIN
listcust := list_customers();
cust := customer_t(1, 'prabath');
cust2 := customer_t(2, 'jorge');
listcust.extend;
listcust(1) := cust;
listcust.extend;
listcust(2) := cust2;
END;
My DS is this:
<?xml version="1.0" encoding="UTF-8"?>
<data name="UDTSample2">
<config id="default">
<property name="org.wso2.ws.dataservice.driver">oracle.jdbc.driver.OracleDriver</property>
<property name="org.wso2.ws.dataservice.protocol">jdbc:oracle:thin:#localhost:1521:DBMB</property>
<property name="org.wso2.ws.dataservice.user">****</property>
<property name="org.wso2.ws.dataservice.password">****</property>
</config>
<query id="q3" useConfig="default">
<sql>call getCustomer2(?)</sql>
<result element="customers">
<element name="customer" arrayName="custArray" column="cust" optional="true"/>
</result>
<param name="cust" paramType="ARRAY" sqlType="ARRAY" type="OUT" structType="LIST_CUSTOMERS" />
</query>
<operation name="op3">
<call-query href="q3" />
</operation>
</data>
ant return:
<customers xmlns="http://ws.wso2.org/dataservice">
<customer>{1,prabath}</customer>
<customer>{2,jorge}</customer>
</customers>
but I want something like this:
<customers xmlns="http://ws.wso2.org/dataservice">
<customer>
<id>1</id>
<name>prabath<name>
</customer>
<customer>
<id>2</id>
<name>Jorge<name>
</customer>
</customers>
How can I accomplish this?
[1] http://prabathabey.blogspot.com/2012/05/query-udtsuser-defined-types-with-wso2.html
Not sure whether this kind of transformation can be done at DSS level because DSS gives back what it recieves from database. Better use WSO2 esb for this kind of transformation.
By the moment it's not possible to accomplish this scenario using just DSS. the DS response must be send to the WSO2 ESB to do the corresponding transformation before send the response to the client. A JIRA was created to do this in the future https://wso2.org/jira/browse/DS-1104
As a workaround, you can use a procedure returning a sys_refcursor.
It would look like this:
PROCEDURE getCustomer_CUR(cur_cust OUT SYS_REFCURSOR)
l_cust LIST_CUSTOMERS;
IS
-- Retrieve cust list:
getCustomer2(l_cust);
OPEN cur_cust for
select cast(multiset(select * from TABLE(l_cust)) as customer_t) from dual;
...
END;
Then you can do your DSS mapping something like:
<sql>call getCustomer_CUR(?)</sql>
<result element="customers">
<element arrayName="custArray" name="Customers">
<element column="custArray[0]" name="col0" xsdType=.../>
...
</element>
</result>
<param name="cust" sqlType="ORACLE_REF_CURSOR" type="OUT"/>
It is tedious but it works.

sql server 2008 - import data into existing tables from XML files

Before data is removed from an sql server database, it is exported and saved as an XML file in the event that this data is to be recovered at a later stage. I am now trying to get the data back into the database from an XML file but cannot find the best way to do this. The SQL server import / export wizard does not appear to support XML. I have looked at the XML Bulk Load component but this doesn't look like it would work for my issue. Has anyone any suggestions?
The XML may look like below and I woud want each row inserting:
<?xml version="1.0" encoding="UTF-8"?>
<products>
<product>
<prod_id>4235823</prod_id>
<productImageURL>image1.jpg</productImageURL>
<entryDate>Aug 30 2011 01:47:08:317PM</entryDate>
<category>859191</category>
<productDescription>product description 1</productDescription>
<productName>product name 1</productName>
<Price>9.99</Price>
</product>
<product>
<prod_id>8989595</prod_id>
<productImageURL>image2.jpg</productImageURL>
<entryDate>Aug 30 2011 01:47:08:317PM</entryDate>
<category>859191</category>
<productDescription>product description 2</productDescription>
<productName>product name 2</productName>
<Price>2.99</Price>
</product>
<product>
<prod_id>4575454</prod_id>
<productImageURL>image3.jpg</productImageURL>
<entryDate>Aug 30 2011 01:47:08:317PM</entryDate>
<category>859191</category>
<productDescription>product description 3</productDescription>
<productName>product name 3</productName>
<Price>5.99</Price>
</product>
</products>
SELECT
p.value('prod_id[1]','INT'),
p.value('productImageURL[1]','VARCHAR(100)'),
p.value('category[1]','VARCHAR(100)'),
p.value('productDescription[1]','VARCHAR(1000)'),
p.value('productName[1]','VARCHAR(100)'),
p.value('Price[1]','money'),
FROM #xmlfile.nodes('/Products/Product') as Product(p)
After a bit of research I found I needed the following:
DECLARE #xml xml
SET #xml = N'<Products>
<Product>
<id>4</id>
<name>Amy</name>
<age>25</age>
</Product>
<Product>
<id>7</id>
<name>Vicky</name>
<age>40</age>
</Product>
</Products>'
INSERT INTO dbo.leanne_test (id, name, age)
SELECT
doc.col.value('id[1]', 'nvarchar(10)') id
,doc.col.value('name[1]', 'varchar(100)') name
,doc.col.value('age[1]', 'nvarchar(10)') age
FROM #xml.nodes('/Products/Product') doc(col)

Microsoft SQL Server xml data

This site has a technique to pass xml data around in Microsoft SQL Server:
DECLARE #productIds xml
SET #productIds ='<Products><id>3</id><id>6</id><id>15</id></Products>'
SELECT
ParamValues.ID.value('.','VARCHAR(20)')
FROM #productIds.nodes('/Products/id') as ParamValues(ID)
But what is the syntax if I add another field?
The following does NOT work:
DECLARE #productIds xml
SET #productIds ='<Products><id>3</id><descr>Three</descr><id>6</id><descr>six</descr><id>15</id><descr>Fifteen</descr></Products>'
SELECT
ParamValues.ID.value('.','VARCHAR(20)')
,ParamValues.descr.value('.','VARCHAR(20)')
FROM #productIds.nodes('/Products/id') as ParamValues(ID)
Note: Maybe I've constructed my xml wrong.
You need to use something like:
SELECT
ParamValues.ID.value('(id)[1]','VARCHAR(20)'),
ParamValues.ID.value('(descr)[1]','VARCHAR(20)')
FROM
#productIds.nodes('/Products') as ParamValues(ID)
That FROM statement there defines something like a "virtual table" called ParamValues.ID - you need to select the <Products> node into that virtual table and then access the properties inside it.
Furthermore, your XML structure is very badly chosen:
<Products>
<id>3</id>
<descr>Three</descr>
<id>6</id>
<descr>six</descr>
<id>15</id>
<descr>Fifteen</descr>
</Products>
You won't be able to select the individual pairs of id/descr - you should use something more like:
<Products>
<Product>
<id>3</id>
<descr>Three</descr>
</Product>
<Product>
<id>6</id>
<descr>six</descr>
</Product>
<Product>
<id>15</id>
<descr>Fifteen</descr>
</Product>
</Products>
Then you could retrieve all items using this SQL XML query:
SELECT
ParamValues.ID.value('(id)[1]','VARCHAR(20)') AS 'ID',
ParamValues.ID.value('(descr)[1]','VARCHAR(20)') AS 'Description'
FROM
#productIds.nodes('/Products/Product') as ParamValues(ID)
ID Descrition
3 Three
6 six
15 Fifteen
You must wrap each set of id and descr into one parent node. Say Row. Now you can access each pair like this.
DECLARE #productIds xml
SET #productIds ='<Products><Row><id>3</id><descr>Three</descr></Row><Row><id>6</id><descr>six</descr></Row><Row><id>15</id><descr>Fifteen</descr></Row></Products>'
SELECT
ParamValues.Row.query('id').value('.','VARCHAR(20)'),
ParamValues.Row.query('descr').value('.','VARCHAR(20)')
FROM #productIds.nodes('/Products/Row') as ParamValues(Row)

Resources