How to retrieve multiple XML siblings - SQL Server - sql-server

I have searched thoroughly and not found any examples or guidance on how I can query and retrieve the values of multiple XML siblings.
There are plenty of examples on how to retrieve a single sibling value.
For example given the following XML fragment:
<StoreSurvey>
<AnnualSales>800000</AnnualSales>
<AnnualRevenue>80000</AnnualRevenue>
<BankName>United Security</BankName>
<BusinessType>BM</BusinessType>
<YearOpened>1996</YearOpened>
<Specialty>Mountain</Specialty>
<SquareFeet>21000</SquareFeet>
<Brands>2</Brands>
<Internet>ISDN</Internet>
<NumberEmployees>13</NumberEmployees>
<Products Type="Bikes">
<Product>Mountain</Product>
<Product>Road</Product>
<Product>Racing</Product>
</Products>
<Products Type="Clothes">
<Product>Jerseys</Product>
<Product>Jackets</Product>
<Product>Shorts</Product>
</Products>
</StoreSurvey>
If I want to retrieve the value of <AnnualSales>, I can execute the following statement in query analyzer:
SELECT Survey_untyped.query('/StoreSurvey/AnnualSales')
FROM Stores;
The result set will properly display
<AnnualSales>800000</AnnualSales>
However, what if I want to retrieve both <AnnualSales> AND <AnnualRevenue>? How would I do that?
The query should provide a result set looking like:
<AnnualSales>800000</AnnualSales>
<AnnualRevenue>80000</AnnualRevenue>
Or what if I want three of the sibling values “BankName” in addition to those values? Result set would look like this:
<AnnualSales>800000</AnnualSales>
<AnnualRevenue>80000</AnnualRevenue>
<BankName>United Security</BankName>
Does anyone know the answer to that?

This XPath, which uses the self:: axis,
/StoreSurvey/*[self::AnnualSales or self::AnnualRevenue or self::BankName]
will select
<AnnualSales>800000</AnnualSales>
<AnnualRevenue>80000</AnnualRevenue>
<BankName>United Security</BankName>
from your XML, as requested.

Related

Having an issue with XML containing nested objects to POCO (de)serialisation (VB.Net)

I've created an SP in SQL Server that returns as XML. I decided to do this as the information has contacts and addresses in it and I wanted to reduce the amount of data I get.
<Accounts>
<Account>
<Company />
<ContactNumber />
<Addresses>
<Address>
<Line1 />
....
</Address>
<Addresses>
<Contacts>
<Contact>
<Name />
....
</Contact>
<Account>
</Accounts>
I have found SqlCommand.ExecuteXmlReader but I'm confused as to how to serialise this into my POCO. Can someone point me at what my next step is. (The POCO was created by the Insert XML as a class menu item in VS2019).
My Google fu is letting me down as I'm not sure what I should be looking for to help understand how to serialize the XML into something that will allow me to go with Foreach Account in AccountsClass type logic.
Any help is greatly appreciated.
PS The XML above is just a sample to show what I'm doing. The actual data is over 70 fields and with two FK joins the initial 40000 rows is well in excess of 1.8 million once selected as a normal dataset.
EDIT: Just in case someone stumbles on this and are in the same situation I was in.
When preparing a sample record for the Past XML to class make sure you have more than one record if you are expecting something similar to my example above. (The class changes to support more than one record.)
You get very different results when searching for deserialize when doing your research. This small change resulted in me figuring out the issue.

XML Attributes to SQL

I've seen posts that are similar to what I'm about to ask, but I can't find anything that actually solves my problem. I've seen (and duplicated) getting XML tags into SQL, but not getting the attributes of the tags into SQL.
Background: We use a program that runs "events" based on each event's schedule. The schedules are in XML. Ultimately, I'm trying to compare the last time a given event ran to the last time it should have run, based on its schedule. Once I get the schedules out of XML and into a table (or tables), I'm confident I can take it from there. But, I'm STRUGGLING with that first step.
Below is the XML I'm trying to get into a table (or tables). Any help would be greatly appreciated!!
<Schedule LastModified="2016-06-27T21:02:10.6041531Z" TimeZone="(UTC-06:00) Central Time (US & Canada)" ConvertedToUTC="True" Type="Weekly">
<Beginning StartDate="2016-05-26T22:26:00.0000000" />
<Block BlockType="AllDay" Interval="10" IntervalType="Minute" SetType="Inclusive" Start="15:00:00" End="17:00:00" Duration="02:00:00" />
<Interval Type="Weekly" RecurEveryX="1" Sunday="False" Monday="True" Tuesday="True" Wednesday="True" Thursday="True" Friday="True" Saturday="False" />
<Ending Type="NoEndDate" />
</Schedule>
Don't know, where you have your issues... Reading this XML is rather trivial (did not code all of the values, but you'll get the idea):
DECLARE #mockup TABLE(YourXML XML);
INSERT INTO #mockup VALUES
(N'<Schedule LastModified="2016-06-27T21:02:10.6041531Z" TimeZone="(UTC-06:00) Central Time (US & Canada)" ConvertedToUTC="True" Type="Weekly">
<Beginning StartDate="2016-05-26T22:26:00.0000000" />
<Block BlockType="AllDay" Interval="10" IntervalType="Minute" SetType="Inclusive" Start="15:00:00" End="17:00:00" Duration="02:00:00" />
<Interval Type="Weekly" RecurEveryX="1" Sunday="False" Monday="True" Tuesday="True" Wednesday="True" Thursday="True" Friday="True" Saturday="False" />
<Ending Type="NoEndDate" />
</Schedule>');
SELECT m.YourXML.value(N'(/Schedule/#LastModified)[1]',N'datetime') AS Schedule_LastModified
,m.YourXML.value(N'(/Schedule/#TimeZone)[1]',N'nvarchar(max)') AS Schedule_TimeZone
,m.YourXML.value(N'(/Schedule/Beginning/#StartDate)[1]',N'datetime') AS Beginning_StartDate
,m.YourXML.value(N'(/Schedule/Block/#BlockType)[1]',N'nvarchar(max)') AS Block_BlockType
,m.YourXML.value(N'(/Schedule/Block/#Interval)[1]',N'int') AS Block_Interval
,m.YourXML.value(N'(/Schedule/Interval/#Type)[1]',N'nvarchar(max)') AS Interval_Type
FROM #mockup AS m;
If this is not your solution, please edit your question: Add your own attempt, the wrong output and the expected output. Your explanation did not make is all clear to me...

Mule Database Connector Multiple Queries

I am running multiple select queries and I want them to run one after the other.
In this example, I select account numbers then use those numbers in the following query. Will the queries run consecutively one after the other i.e. next query only runs after the previous query has finished. Do I need to wrap them in a composite-source and wrap them in a transaction? What would that look like?
<flow name="PopulateAccount">
<db:select config-ref="dsConfig" doc:name="Get Account ID">
<db:paramterized-query><![CDATA[
SELECT ACC_NUM....
</db:select>
<custom-transformer class="com.vf.ListTransformer">
<set-session-variable variableName="messageID" value="#[payload]"
doc:name="Set Account IDs"/>
<!-- The next query depends on the Account IDS from
previous results in the session variable -->
<db:select config-ref="dsConfig" doc:name="Get Account Detail">
<db:paramterized-query><![CDATA[
SELECT ACC_NAME,....
</db:select>
<custom-transformer class="com.vf.AccountsTransformer">
<!-- More database operations --->
</flow>
Will the queries run consecutively one after the other
yes, as long as you do not take any measures to run them in parallel, like for example moving the database component in a separate flow and call it in a asynchronous way.
Do I need to wrap them in a composite-source
no, especially not if you use the result of the first query in the second query (like in your example)
and wrap them in a transaction
why? you are not inserting/updating anything in your example.
What would that look like?
just like in your example. the only thing i would change is the way how you store the result of your first query. although there is nothing wrong with using set-variable i prefer using a enricher to store result of a component in variable instead of changing the payload and setting the variable afterwards.
<flow name="testFlow">
<enricher target="#[flowVars.messageID]" doc:name="Message Enricher">
<db:select config-ref="MySQL_Configuration" doc:name="select ACC_NUM">
<db:parameterized-query><![CDATA[SELECT ACC_NUM ...]]></db:parameterized-query>
</db:select>
</enricher>
</flow>

Where is the data saved, from the Datatable-items, in ECM eRoom-database?

I am trying to retrieve data out of the ECM eRoom Database (which isn't documented, as I know of).
I have an eRoom with an custom "Database", some Fields.
When I query the objects table I find the "Database" row
select * from[dbo].[Objects] where internalId = 1234567
and the Rows for the entries
select top 10 * from[dbo].[Objects] where parentInternalId = 1234567
but I don't find any field with the values of the entries, only an Column with NonSearchableProperties., that is only full with Hex Data.
My Question(s),
how could i retrieve the values?
Is it possible to retrieve them with mere SQL?
What is the simplest way?
This is not the silver bullet, but it is okay for my usecase
After long goolging and alot of test scripts, i found some answers, but probably due to the fact the the system is soon end-of-life and that the documentation is not easy to read, here are my finding.
Is it possible to retrieve them with mere SQL?
As far as I could find out, no! (please correct me If I'm wrong)
how could i retrieve the values?
With the eRoom API(on the Server there are some Sample programms to query the data/objects <installation-path>\eRoom Server\Toolkit\Samples, with c++, vb, vbscript, ... all a bit to much overhead), or with the eRoom XML Query Language(exql) over soap calls.
What is the simplest way?
After alot of tests, searching in forums and many tests with soap ui. I found out that queries with exql seem to be the simplest way to retrieve Data, if you understand the structure.
Here some ressource that were helpful:
(very) Basic info of exql from the manufacturer https://eroom.asce.org/eRoomHelp/en/XML_Help/Introduction.htm
(disclaimer: I didn't find it helpful, but it shows at least some basics)
short 9 page Developer guide https://developer-content.emc.com/developer/downloads/eRoomXMLCapabilitiesUseCaseProgramDashboard.pdf (the last example on page 8, helped me understand how to setup the query, with alot of fantasy)
But for this to work, don't forget, to activate Allow XML queries and commands from external applications in the Site Settings
TIP 1:
you always can go go deeper you just need to know the right xml-element under. <Database>, <Cells> and <DBCell> can help you go deeper
TIP 2:
don't query to much data since this query likely run into timeouts
Update 1:
Just to save time for anyone who is looking, this "query" returns all rows (properties) for a Database(s) created in an eRoom Root.
(don't forget to set facility and room in the Url ex. http://server/eroomxml/facilities/TEST/Rooms/TestRoom, although it could be set in the query)
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:er="http://www.eroom.com/eRoomXML/2003/700">
<soapenv:Header/>
<soapenv:Body>
<er:ExecuteXMLCommand>
<er:eRoomXML>
<er:command er:select="HomePage/Items">
<er:getproperties>
<er:Item>
<Database>
<Rows>
<Item>
<Cells>
<DBCell>
<Content>
</Content>
</DBCell>
</Cells>
</Item>
</Rows>
</Database>
</er:Item>
</er:getproperties>
</er:command>
</er:eRoomXML>
</er:ExecuteXMLCommand>
</soapenv:Body>
</soapenv:Envelope>

How to write a query like SQL's SELECT x FROM

I want to write a query that does something like this SQL query:
SELECT name FROM contacts WHERE blah blah
I know I can do something like this:
for contact in Contacts.gql(WHERE_CLAUSE, args).fetch(1000):
print contact.name
but isn't there a way to get name directly from a query without having to loop on the results? would it provide any advantage in performance?
Nope. Can't be done.
A GQL query returns zero or more entities or Keys of the requested
kind. Every GQL query always begins with either SELECT * or SELECT
key. (A GQL query cannot perform a SQL-like "join" query.)
http://code.google.com/appengine/docs/python/datastore/gqlreference.html
But you can create a simple wrapper to do it for you. Something like:
def get_all_of_field(model, field):
for x in model.all():
yield getattr(x, field)
names = get_all_of_field(Contact, 'name')
Performance can't be improved that way as the entire "line" is read by the API no matter what. Either you read the entire "line" or just its key.
You can do this now using Projection queries. For db, see the documentation here:
https://developers.google.com/appengine/docs/python/datastore/projectionqueries
For ndb, see the documentation here:
https://developers.google.com/appengine/docs/python/ndb/queries#projection

Resources