How can I use SQL in XMLA for SSAS? - sql

I have a problem with usage of SQL in XMLA for SSAS. It is required for Python library that interacts with SSAS server using SOAP protocol. There are 2 ways to reach data: MDX (multidimentional mode) and SQL (tabular mode). I have a simple task to select data from 1 table. So SQL should fit best, but it has too many limitations: there is no groups, havings, limits, also WHERE clause is limited to "=" operator. So it cannot be used for large tables in real world.
Example of code:
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" xmlns="urn:schemas-microsoft-com:xml-analysis">
<soap-env:Body>
<Execute>
<Command>
<Statement>
SELECT [Customer Id] as [Customer.Customer Id] ,[Title] as [Customer.Title]
FROM [Adventure Works Internet Sales Model].[$Customer]
WHERE ([Customer Id]="11000" OR [Customer Id]="11001" OR [Customer Id]="11002" OR [Customer Id]="11003" OR [Customer Id]="11004")
</Statement>
</Command>
<Properties>
<PropertyList>
<Format>Tabular</Format>
<AxisFormat>TupleFormat</AxisFormat>
<MaximumRows>2</MaximumRows>
</PropertyList>
</Properties>
</Execute>
</soap-env:Body>
</soap-env:Envelope>
Also, "MaximumRows" doesn't works here. Result is next:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ExecuteResponse xmlns="urn:schemas-microsoft-com:xml-analysis">
<return>
<root xmlns="urn:schemas-microsoft-com:xml-analysis:rowset" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msxmla="http://schemas.microsoft.com/analysisservices/2003/xmla">
<xsd:schema targetNamespace="urn:schemas-microsoft-com:xml-analysis:rowset" xmlns:sql="urn:schemas-microsoft-com:xml-sql" elementFormDefault="qualified">
<xsd:element name="root">
<xsd:complexType>
<xsd:sequence minOccurs="0" maxOccurs="unbounded">
<xsd:element name="row" type="row" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:simpleType name="uuid">
<xsd:restriction base="xsd:string">
<xsd:pattern value="[0-9a-zA-Z]{8}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{12}" />
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="xmlDocument">
<xsd:sequence>
<xsd:any />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="row">
<xsd:sequence>
<xsd:element sql:field="Customer.Customer Id" name="Customer.Customer_x0020_Id" type="xsd:string" minOccurs="0" />
<xsd:element sql:field="Customer.Title" name="Customer.Title" type="xsd:string" minOccurs="0" />
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
<row>
<Customer.Customer_x0020_Id>11000</Customer.Customer_x0020_Id>
</row>
<row>
<Customer.Customer_x0020_Id>11001</Customer.Customer_x0020_Id>
</row>
<row>
<Customer.Customer_x0020_Id>11002</Customer.Customer_x0020_Id>
</row>
<row>
<Customer.Customer_x0020_Id>11003</Customer.Customer_x0020_Id>
</row>
<row>
<Customer.Customer_x0020_Id>11004</Customer.Customer_x0020_Id>
</row>
</root>
</return>
</ExecuteResponse>
</soap:Body>
</soap:Envelope>
So, my next investigation was using MDX query. I know it's more powerful. And I also can use XMLA for that. But I cannot realize how to get data in "tabular" mode.
Something like that:
select {[Customer].members} on columns
from [Adventure Works Internet Sales Model]
But I cannot reach this goal for now. Can someone help me?

Related

Invalid XML element location. (SQL-XSD)

I just started learning XML today. I was trying to create a 'sample' XSD and populate it but.. I made up my data and it looks fine, but I can't make this schema work..
CREATE XML SCHEMA COLLECTION GenreTestSchema
AS
<?xml version = "1.0" encoding = "UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<!--create group for GENRELIST-->
<xsd:group name="GENRELISTGROUP">
<xsd:element name="GENRELIST">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="GENRE" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="REFERENCE" minOccurs="0" maxOccurs="100" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:group>
</xsd:schema>
Now If I remove this element
<xsd:element name="GENRELIST">
and all the code that goes with it so (element and complextype) then the schema works fine. I can't figure out what is wrong here and why it doesn't let me create this element?
Errorlog
Element <element> is not valid at location '/*:schema[1]/*:group[1]/*:element[1]'.
It talks about invalid location but I literally have no idea why?
Data sample
<GENRELIST xmlns="http://myGenres">
<GENRE GenreNo="1">
<GENRE>Fiction</GENRE>
<REFERENCE>Alien</REFERENCE>
</GENRE>
<GENRE GenreNo="2">
<GENRE>Tragedy</GENRE>
<REFERENCE>Titanic</REFERENCE>
</GENRE>
</GENRELIST>
The problem is that you're missing to take the namespace xmlns="http://myGenres" into account on the element GENRELIST.
So transform your anonymous complex type to a named type and use the namespace on it:
<?xml version = "1.0" encoding = "UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:gl="http://myGenres"
targetNamespace="http://myGenres"
elementFormDefault="qualified">
<xsd:complexType name="genrelist"> <!-- named type 'genrelist' -->
<xsd:sequence>
<xsd:element name="GENRE" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="REFERENCE" minOccurs="0" maxOccurs="100" />
</xsd:sequence>
</xsd:complexType>
<!--create group for GENRELIST-->
<xsd:element name="GENRELIST" type="gl:genrelist" /> <!-- applying the 'gl' namespace to named type 'genrelist' -->
</xsd:schema>
This way your XML will be validated.
For the purpose of targetNamespace look here and for
elementFormDefault look there.
I don't know why you're trying to create an xs:group (a "model group"). A model group is a reusable chunk of schema declarations that can be used in several places, handy when you have multiple elements with similar structure. It might sometimes make sense to have a group with only one reference to it, but it can't make sense to have a group with no references to it.
Now there's an additional (and related) problem). Typically when you start validating an instance document, the validator looks for a global element declaration whose name matches the root element of the instance. But you don't have a global element declaration in your schema; your declaration of GENRELIST isn't global because it is in a group.

How to validate SQL Server 2008 XML typed datatype using XML SCHEMA COLLECTION

Still learning about using XML in SQL Server 2008. It seems many of the examples I've seen demonstrating how to validate XML data using XML Schema Collection are validating XML of a known size. My problem is that the XML data that I'm working with can have 'X' number of Kit elements.
The validation works fine if there is just one kit, but if multiple <xsd:element name="Kit"> elements are in the XML then I get error:
XML Validation: Unexpected element(s): Kit. Location: /:KitStatus[1]/:Kits[1]/:Kit[2]*
My code:
CREATE XML SCHEMA COLLECTION [dbo].[KitStatusSchema] AS
N'<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="KitStatus" >
<xsd:complexType>
<xsd:sequence>
<xsd:element name="ClientID"/>
<xsd:element name="Kits">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="NumberofKits"/>
<xsd:element name="Kit">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="PackageNumber"/>
<xsd:element name="KitNumber"/>
<xsd:element name="LocationNumber"/>
<xsd:element name="Status"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Is it possible for the validation to validate 1 or multiple Kits?

SQLXMLBulkLoad Schema Validation Issue (Easy)

I have a huge XML file full of employees and information, and have a question.
Example of XML File:
<Employees>
<Employee>
<EmployeeID>blah</EmployeeID>
<FirstName>blah</FirstName>
<LastName>blah</LastName>
<MiddleName>blah</MiddleName>
.......... and on
</Employee>
........ and on
</Employees>
My schema, so far is like this:
<?xml version="1.0" encoding="utf-8"?>
<xsd:element name="Employees" sql:relation="The_Employees">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Employee">
<xsd:element name="EmployeeID" sql:field="EmpNo" type="xsd:integer"/>
<xsd:element name="FirstName" sql:field="FirstName">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:whiteSpace value="collapse"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
.......... and on
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
From my research, the root element is supposed to contain the relation with your table in the DB (for privacy sake, the name in this example is "The_Employees") So, I made that relation, and also made the sql:field for each column in the table because the column names are different than the XML Element tags in most cases. However, in what ways to do I relate each individual <Employee> tag to my table? Also, whilst validating the XML, it throws this error:
The content of 'Employee' must match (annotation?, (simpleType |
complexType)?, (unique | key | keyref)*)). A problem was found
starting at: element.
It seems like the validator is thinking that I am trying to split the content into two separate tables and therefore need to annotate that, but I am not. Any suggestions?
Just FYI: The end product here is going to be a VB.NET program which uses SQLXMLBulkLoad to load the data from the XML file into a fresh SQL Table.
Alright... the fix was simple and I am answering this so that someone in the future may refer to it. If you have a root element as well as each individual parent element under that root element and you are using BulkLoad, then you can set the root element to sql:is-constant = 1. This tells the schema that the root element exists, but to ignore it. Also, the above schema was ammended to:
<xsd:element name="Employees" sql:is-constant=1>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Employee" sql:relation="The_Employees">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="EmployeeID" sql:field="EmpNo" type="xsd:integer"/>
<xsd:element name="FirstName" sql:field="FirstName">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:whiteSpace value="collapse"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
.......... and on
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>

any element in XML schema blocks XQuery

I have the following XML Schema:
CREATE XML SCHEMA COLLECTION test AS '
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="PointConf">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="GlobalFlags">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Order" type="OrderType"/>
<xsd:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="OrderType">
<xsd:attribute name="value" type="xsd:int" />
</xsd:complexType>
</xsd:schema>
'
GO
Then I use it in this way:
DECLARE #xml xml(test)
SET #xml='<PointConf>
<GlobalFlags>
<Order value="1" />
</GlobalFlags>
</PointConf>'
SELECT #xml.value('(/PointConf/GlobalFlags/Order/#value)[1]','int')
SELECT gives me the following error:
XQuery [value()]: 'value()' requires a singleton (or empty sequence), found operand of type '(xs:int | xdt:anyAtomicType *) ?'
Without the xsd:any element in the schema the code above works without any errors. What am I doing wrong?
I got the select to work by using the statement
SELECT #xml.value('string(/PointConf[1]/GlobalFlags/Order[1]/#value)','int')
I understand the requirement for the [1] index on the Order node, as this can be a list, however I don't see why its required for the PointConf node.
The [1] needs to be used at the actual level where a list exists to restrict that list to a single return value
The string(...) turns the node set into a string (or empty string). I think this helps with the xsd:any although I'm not completely sure why - something to do with handling the possibility of the node Order being missing completely I think.
Update:
Investigating further:
SELECT #xml.value('string((/PointConf/GlobalFlags/Order/#value)[1])','int')
also works.
So its just the string function that's required to make it work in this instance.

Why my test xml is failing with very simple XSD Schema?

I am a bit novice in xml schema. I would be grateful if somebody help me out to understand why my xml is not being validated with the schema:
Here is my Schema:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/testSchema" xmlns="http://www.example.org/testSchema">
<xs:element name="Employee">
<xs:complexType>
<xs:sequence>
<xs:element name="Name">
<xs:complexType>
<xs:sequence>
<xs:element name="FirstName" />
<xs:element name="LastName" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Here is my test xml:
<?xml version="1.0" encoding="UTF-8"?>
<Employee xmlns="http://www.example.org/testSchema">
<Name>
<FirstName>John</FirstName>
<LastName>Smith</LastName>
</Name>
</Employee>
I am getting following error by Eclipse xml editor/validator:
cvc-complex-type.2.4.a: Invalid content was found starting with element 'Name'. One of '{Name}' is expected.
I could not understand what is wrong with this schema or my xml.
all u have to do is add elementFormDefault="qualified" and u will be fine. to understand this behavior, read "Are You Qualified?" section # http://msdn.microsoft.com/en-us/library/ms950796.aspx
Just add the elementFormDefault="qualified" to the schema attribues.
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org/testSchema"
elementFormDefault="qualified"
xmlns="http://www.example.org/testSchema">
And your original will work
<?xml version="1.0" encoding="utf-8"?>
<Employee xmlns="http://www.example.org/testSchema">
<Name>
<FirstName>John</FirstName>
<LastName>Smith</LastName>
</Name>
</Employee>
Looks like you're failing to specify how to validate the FirstName and LastName elements; give the element specs for those type="xsd:string" (where xsd needs to be mapped to the XML Schema Datatypes namespace, of course) and all should be well.
But you are better off not nesting those elements so deep. Put them all at the same level and use ref="Name" to link them all together instead; it makes your schema much more flexible and usable.