Parsing xml in SQL Server 2008 with multiple xml namespace - sql

I want to get gid and uid from the below xml. This xml exists as a column in a SQL Server 2008 table called xmlmsg. I need a SQL query that parses the table which has an xml column with the data like below:
<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://api.money.com/schema/contact" Email=""
gId="11" uId="uadgra45678" Timestamp="2013-10-17T19:19:41Z"
xsi:schemaLocation="http://api.money.com/schema/contact http://api.money.com/schema/contact/contact-1.2.xsd">
</person>

(This is really a comment because it doesn't seem to answer the question implied by the title.)
This query (from LinqPad) creates and retrieves XML data:
--Drop Table #TempXml
Create Table #TempXml(Value XML)
Insert Into #TempXml(Value)Values('<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://api.money.com/schema/contact" Email=""
gId="11" uId="uadgra45678" Timestamp="2013-10-17T19:19:41Z"
xsi:schemaLocation="http://api.money.com/schema/contact http://api.money.com/schema/contact/contact-1.2.xsd">
</person>')
Select count(*) from #TempXml;
Select * from #TempXml;
Select Value.value('declare namespace AMC="http://api.money.com/schema/contact";
/AMC:person[1]/#uId','varchar(max)')
,Value.value('declare namespace AMC="http://api.money.com/schema/contact";
/AMC:person[1]/#gId','int')
From #TempXml;
Drop Table #TempXml

Related

Selecting XML nodes with SQL Server

My XMLData is stored under table.[column] : dbo.promotions.[PromotionDiscountData]
and the XML looks like the following when i expand it:
<ArrayOfPromotionDiscountBase xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<PromotionDiscountBase xsi:type="OrderPromotionDiscount">
<DiscountType>Fixed</DiscountType>
<DiscountAmount>5.0000</DiscountAmount>
</PromotionDiscountBase>
</ArrayOfPromotionDiscountBase>
I would like to export a report and flatten out the xml as a column with everything else in the dbo.promotions table.
What would be the best way to get the DiscountType and DiscountAmount Out of the xml?
Thanks!
Please try the following.
SQL
-- DDL and data population, start
DECLARE #tbl TABLE (ID INT IDENTITY(1,1) PRIMARY KEY,[xmlData] XML NOT NULL);
INSERT INTO #tbl([xmlData])
VALUES
(N'<ArrayOfPromotionDiscountBase xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<PromotionDiscountBase xsi:type="OrderPromotionDiscount">
<DiscountType>Fixed</DiscountType>
<DiscountAmount>5.0000</DiscountAmount>
</PromotionDiscountBase>
</ArrayOfPromotionDiscountBase>');
-- DDL and data population, end
SELECT ID
, col.value('(DiscountType)[1]', 'VARCHAR(30)') AS [DiscountType]
, col.value('(DiscountAmount)[1]', 'DECIMAL(10,4)') AS [DiscountAmount]
FROM #tbl AS tbl
CROSS APPLY tbl.[xmlData].nodes('/ArrayOfPromotionDiscountBase/PromotionDiscountBase') AS tab(col);

SQL Update XML Value stored in ntext colum

I need to update two values within XML data that is stored in a ntext column. I have a copy of the database to test with, and I haven't been successful with the information I have found.
Here is a sample the XML that I need to update:
<?xml version="1.0" encoding="utf-16"?>
<cmnReportExportParameters xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<DSNs>
<ReportDSN>
<Name>Name</Name>
<Database>DBName</Database>
<Server />
<User>user</User>
<Password>removed </Password>
<DevelopmentName>DBName</DevelopmentName>
</ReportDSN>
</DSNs>
</cmnReportExportParameters>
I need to update the "user" and "password" fields within this XML data. This is part of a legacy CMS application, and I am simply supporting the system (I'm not the developer).
I can cast the data successfully select Name, Parameters, CAST(parameters as xml) from tablename
Any guidance is appreciated.
This is far from ideal, but this is the only way I can think to do it. As your column is the wrong data type (ntext) you can't use the modify XQUERY command. Thus, you have to insert your data into a temporary table, update it, and then reinsert it. This is not going to be great for performance, but it works. As I said before, fixing the data type will make this far easier:
CREATE TABLE [sample] (YourIDCol int IDENTITY(1,1),
NotXML ntext);
INSERT INTO [sample] (NotXML)
VALUES (
N'<?xml version="1.0" encoding="utf-16"?>
<cmnReportExportParameters xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<DSNs>
<ReportDSN>
<Name>Name</Name>
<Database>DBName</Database>
<Server />
<User>user</User>
<Password>removed </Password>
<DevelopmentName>DBName</DevelopmentName>
</ReportDSN>
</DSNs>
</cmnReportExportParameters>');
GO
CREATE TABLE #UpdateXML (ID int, ActualXML xml);
INSERT INTO #UpdateXML (ID,ActualXML)
SELECT YourIDCol,
TRY_CONVERT(xml,NotXML)
FROM [sample]
WHERE TRY_CONVERT(xml,NotXML) IS NOT NULL
AND YourIDCol = 1; --if you need it
UPDATE #UpdateXML
SET ActualXML.modify('replace value of (cmnReportExportParameters/DSNs/ReportDSN/User/text())[1] with ("NewUsername")');
UPDATE #UpdateXML
SET ActualXML.modify('replace value of (cmnReportExportParameters/DSNs/ReportDSN/Password/text())[1] with ("NewPassword")');
UPDATE S
SET NotXML = CONVERT(ntext,CONVERT(nvarchar(MAX),U.ActualXML)) --yuck
FROM [sample] S
JOIN #UpdateXML U ON S.YourIDCol = U.ID;
SELECT *
FROM [sample];
DROP TABLE #UpdateXML;
GO
DROP TABLE [sample];

How can I query a value in a XML column in SQL Server 2008

I have following XML stored in a XML column in a SQL Server database table.
<?xml version="1.0" encoding="UTF-8" ?>
<ns0:Root>
<ns0:Result>
<ns0:AStatus>Aaa</ns0:AStatus>
<ns0:BStatus>Bbb</ns0:BStatus>
</ns0:Result>
</ns0:Root>
I'd like to get value "Aaa", by firing SQL query.
Your XML data is incomplete - it uses a namespace prefix ns0 without defining it anywhere... I've added some arbitrary, totally made-up XML namespace here in my sample - you need to check what that XML namespace actually is in your case and adapt the sample accordingly!
Try this:
DECLARE #InputTable TABLE (ID INT NOT NULL, XmlData XML)
INSERT INTO #InputTable(ID, XmlData) VALUES(42, '<?xml version="1.0" encoding="UTF-8" ?>
<ns0:Root xmlns:ns0="urn:some-sample-xml-namespace">
<ns0:Result>
<ns0:AStatus>Aaa</ns0:AStatus>
<ns0:BStatus>Bbb</ns0:BStatus>
</ns0:Result>
</ns0:Root>')
-- define the XML namespace to use
;WITH XMLNAMESPACES('urn:some-sample-xml-namespace' AS x)
SELECT
ID,
XC.value('(x:AStatus)[1]', 'varchar(50)')
FROM
#inputtable
CROSS APPLY
-- get a "pseudo" table of nodes <ns0:Root>/<ns0:Result>
XmlData.nodes('x:Root/x:Result') AS XT(XC)
Basically, you need to have a definition for your XML namespace prefix - and in the SELECT against this XML data, you need to have the same XML namespace (even though - as shown - the prefix assigned to that namespace can be different - but the namespace must match!).
This then selects the data from the table, and for the XML data, it uses the .nodes() XQuery function to get a list of XML element that match this XPath expression - and it gets these nodes as a in-memory pseudo table XT with a single XML column XC from which you can then again fetch values (like reaching into the first <ns:AStatus> element).

Selective XML indexing in SQL Server

I have a table that has thousands of rows that has the following data in the column named OldValue:
<attendance xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<CalendarId>100</CalendarId>
<PeriodId>1019</PeriodId>
<PersonId>10457</PersonId>
<Date>2012-01-04 00:00:00</Date>
<ExcuseId>884</ExcuseId>
</attendance>
I am trying to set a selective xml index. Here is what I have done so far:
Creating the selective XML Index:
CREATE SELECTIVE XML INDEX sxi_Test ON [dbo].[mytable](OldValue)
WITH XMLNAMESPACES ('http://www.w3.org/2001/XMLSchema-instance' as yming)
FOR
(
pathWH2 = '/yming:Attendance/PersonId' AS XQUERY 'xs:string' SINGLETON
);
GO
Querying the index always returns 0 rows:
WITH XMLNAMESPACES ('http://www.w3.org/2001/XMLSchema-instance' as yming)
SELECT COUNT(*)
FROM mytable
WHERE OldValue.exist(N'(/yming:Attendance/yming:PersonId[.=10457])') = 1
GO
Any suggestions? Thank you.
I usually stumble into a solution with anything involving XML namespaces in SQL, but this seems to work for me:
DECLARE #x XML = '<attendance xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <CalendarId>100</CalendarId> <PeriodId>1019</PeriodId> <PersonId>10457</PersonId> <Date>2012-01-04 00:00:00</Date> <ExcuseId>884</ExcuseId> </attendance>';
WITH XMLNAMESPACES ('http://www.w3.org/2001/XMLSchema-instance' as yming)
SELECT #x.exist(N'(/attendance/PersonId[.=10457])')
GO

Select SQL Query to get xml node values from ntext column?

I want to get one xml node value from NTEXT column which contains xml based on where clause quering on another xml node value.
RDBMS Type: Microsoft SQL Server T-SQL
Here: I want to get Code node value based on StoreId where clause value. How do I get it?
Input: 100
Output:ABCDE
For example:
<root>
<StoreProfile>
<General>
<StoreId>100</StoreId>
<Code>ABCDE</Code>
</General>
</StoreProfile>
</root>
If you are using SQL Server 2005 or 2008 you can use XQuery like so:
For more on XQuery see XQuery Language Reference
DECLARE #storeId INT
SET #storeId = 100
CREATE TABLE #TestTable
(
xmlColumn NTEXT
)
INSERT INTO #TestTable (xmlColumn) Values('<root><StoreProfile><General><StoreId>100</StoreId><Code>ABCDE</Code></General></StoreProfile></root>')
INSERT INTO #TestTable (xmlColumn) Values('<root><StoreProfile><General><StoreId>200</StoreId><Code>FGHIJ</Code></General></StoreProfile></root>')
SELECT
StoreProfile.value('Code[1]', 'nvarchar(10)') as Code
FROM #TestTable
CROSS APPLY (SELECT CAST(xmlColumn AS XML)) AS A(B)
CROSS APPLY A.B.nodes('//root/StoreProfile/General[StoreId = sql:variable("#storeId")]') AS StoreProfiles(StoreProfile)
DROP TABLE #TestTable