How to get rid of XML "_x0040_" attribute prefix in SQL? - sql-server

I'm trying to export a table's content to XML, like this:
CREATE TABLE TEMPTABLE_Results ([#Id] int)
INSERT INTO TEMPTABLE_Results
SELECT 1 as [#Id];
SELECT * FROM TEMPTABLE_Results
FOR XML RAW('Node'), TYPE, XMLSCHEMA('Node')
DROP TABLE TEMPTABLE_Results
But the result has an annoying "x0040" prefix in the attribute:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes" targetNamespace="Node" elementFormDefault="qualified">
<xsd:import namespace="http://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="http://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd" />
<xsd:element name="Node">
<xsd:complexType>
<xsd:attribute name="_x0040_Id" type="sqltypes:int" />
</xsd:complexType>
</xsd:element>
</xsd:schema>
<Node xmlns="Node" _x0040_Id="1" />
I was previously using a table-type variable, but according to this answer, the prefix is added when the table is temporary; but even with a regular table, the prefix is still there.
Any help is much appreciated.

Found: no need to specify "#" for field in order to get it as an attribute instead of an element.
This yields the desired result:
CREATE TABLE TEMPTABLE_Results (Id int)
INSERT INTO TEMPTABLE_Results
SELECT 1 as Id;
SELECT * FROM TEMPTABLE_Results
FOR XML RAW('Node'), TYPE, XMLSCHEMA('Node')
DROP TABLE TEMPTABLE_Results
The resulting XML is:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes" targetNamespace="Node" elementFormDefault="qualified">
<xsd:import namespace="http://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="http://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd" />
<xsd:element name="Node">
<xsd:complexType>
<xsd:attribute name="Id" type="sqltypes:int" />
</xsd:complexType>
</xsd:element>
</xsd:schema>
<Node xmlns="Node" Id="1" />

Related

How to use datetime2 type in XML SCHEMA?

I'm trying to use SQL Server XML SCHEMA types like datetime2 in collections and tables
CREATE XML SCHEMA COLLECTION [XmlValuesSchemaCollection_datetime2] AS
'<?xml version="1.0"?>
<xsd:schema
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes/sql2008/SqlTypes.xsd"
attributeFormDefault="unqualified" elementFormDefault="qualified">
<xsd:element name="datetime2" type="xsd:datetime2"/>
</xsd:schema>';
GO
CREATE TABLE XmlValuesTable_datetime2 (
[uid] [int] IDENTITY PRIMARY KEY,
v XML(XmlValuesSchemaCollection_datetime2) NOT NULL
);
GO
INSERT INTO XmlValuesTable_datetime2 (v)
VALUES (N'<datetime2 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">2014-06-18 06:39:05.190</datetime2>');
GO
but I have error Reference to an undefined name 'datetime2' within namespace 'http://www.w3.org/2001/XMLSchema'. Same with type="xsd:datetime2" - error
Reference to an undefined name 'datetime2' within namespace 'http://schemas.microsoft.com/sqlserver/2004/sqltypes/sql2008/SqlTypes.xsd'
It suppose to work somehow, types described in https://learn.microsoft.com/en-us/previous-versions/sql/sql-server-2008-r2/bb677236(v=sql.105)?redirectedfrom=MSDN but unfortunately I have no clue what is wrong.
Erland Sommarskog answered at msdn
Solution is
CREATE XML SCHEMA COLLECTION [XmlValuesSchemaCollection_datetime2] AS
'<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes" attributeFormDefault="unqualified" elementFormDefault="qualified">
<xsd:import namespace="http://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="http://schemas.microsoft.com/sqlserver/2004/sqltypes/sql2008/sqltypes.xsd"/>
<xsd:element name="datetime2" type="sqltypes:datetime2"/>
</xsd:schema>';

How to write `select ... FOR XML` queries that generates an xml and an xsd so, that they are kitchen ready for an SQLXMLBulkLoad?

I'm looking for the most easy way to export a table (or a part of it) to an xml file and then import this xml file into a corresponding table in some other database.
The principle I found is very simple:
Export: on the source database I generate an xml string and also an xsd schema string by adding a FOR XML root('Data') and FOR XML, XMLSCHEMA clauses to the select query.
Import: on the target database I bulkload the generated xml file by SQLXMLBulkLoad using the generated xsd.
But I can't do exactly this. Between the export and the import I have to make some minor modifications in the xsd schema.
For example, I generate the xml and the xsd strings by the following queries:
select top 3 * FROM myTable
FOR XML AUTO, ELEMENTS
,Root('Data')
and
SELECT top 0 * FROM myTable
FOR XML AUTO, ELEMENTS
,XMLSCHEMA
The resulting generated.xml and generated.xsd look so:
<Data>
<myTable>
<field1>value11</field1>
...
<field1>value1n</field1>
</myTable>
<myTable>
<field1>value21</field1>
...
<field1>value2n</field1>
</myTable>
<myTable>
<field1>value31</field1>
...
<field1>value3n</field1>
</myTable>
</Data>
and
<xsd:schema
targetNamespace="urn:schemas-microsoft-com:sql:SqlRowSet1"
xmlns:schema="urn:schemas-microsoft-com:sql:SqlRowSet1"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes"
elementFormDefault="qualified">
<xsd:import namespace="http://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="http://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd"/>
<xsd:element name="myTable">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="field1" type="..." .../>
...
<xsd:element name="fieldn" type="..." ... />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
But if I want to bulkload by a vb script like this
set objBL = CreateObject("SQLXMLBulkLoad.SQLXMLBulkload.4.0")
objBL.ConnectionString = "provider=SQLOLEDB.1;data source=localhost\SQLEXPRESS;database=Testdb;uid=sa;pwd=*****"
objBL.ErrorLogFile = ".\error.xml"
objBL.KeepIdentity = False
objBL.Execute "generated.xsd", "generated.xml"
set objBL=Nothing
then this works only if I make the following modifications in the generated.xsd
remove this xsd:schema attribute: targetNamespace="urn:schemas-microsoft-com:sql:SqlRowSet1"
add this xsd:schema attribute: xmlns:sql="urn:schemas-microsoft-com:mapping-schema"
Replace the <myTable> element by a sequence of <myTable> elements and wrap the whole into a <xsd:element name="Data" sql:is-constant="1"> element
Add the attributes maxOccurs="unbounded" sql:relation="myTable" to the <myTable> element
So, the modified xsd which is really suitable to bulkload the generated xml by SQLXMLBulkLoad looks like this:
<xsd:schema
xmlns:sql="urn:schemas-microsoft-com:mapping-schema"
xmlns:schema="urn:schemas-microsoft-com:sql:SqlRowSet1"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes"
elementFormDefault="qualified">
<xsd:import namespace="http://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="http://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd"/>
<xsd:element name="Data" sql:is-constant="1">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="myTable" maxOccurs="unbounded" sql:relation="myTable">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="field1" type="..." .../>
...
<xsd:element name="fieldn" type="..." ... />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
I wonder if the generating sql queries and/or the vbscript can be modified so, that the generated xml and xsd work with the vbscript without any manual modification?
As your question has asked, the SIMPLEST way, which can be highly portable and compatible, can use simple XML data sets like so. Assuming you have two SQL servers. I have used this method between SQL>Excel, SQL>SQL, SQL>Oracle.
You can do on SQL, as a stored procedure call:
DECLARE #xml xml
SET #XML = (
SELECT field1, field2
FROM table
FOR XML RAW('row'), ROOT('data'), ELEMENTS
)
This will return:
<root>
<row>
<field1>SomeData</field1>
<field2>SomeOtherData</field2>
</row>
</root>
Once you have the XML, you simply read into the TARGET database using something like this:
INSERT INTO TargetDatabase.TargetTable(field1, field2)
SELECT tbl.c.value('field1','varchar(1000)'), tbl.c.value('field2','bigint')
FROM #XML.nodes('/root[1]/row) tbl(c)
You can also run queries, etc on the incoming XML data quite easily if needed:
INSERT INTO TargetTable(field1, field2)
SELECT tbl.c.value('field1','varchar(1000)'), tbl.c.value('field2','bigint')
FROM #XML.nodes('/root[1]/row) tbl(c)
WHERE tbl.c.value('field2','bigint') > 100 or tbl.c.value('field1','varchar(1000)') Like '%fish%'
Very efficient and very fast. No need to mess around with schemas. Only thing is that the field types are hard coded.. so you need to custom build each of the SP read/writes.
If you have some sort of agent (e.g. MS Excel doing this), its just a simple case of writing a stored procedure to receive the XML data in the target database:
CREATE PROCEDURE sp_target_for_XML
#XML xml

SQL Server: is it possible to change the value of a complex XML element?

I need to change a value within a XML element - for this untyped version it works this way:
declare #X xml=
'<translations>
<value lang="en-US">example</value>
<value lang="de-DE">Beispiel</value>
</translations>';
set #X.modify('replace value of (/translations/value[#lang="en-US"]/text())[1] with "replacedValue"');
select #X.value('(/translations/value[#lang="en-US"])[1]','varchar(max)');
The select return the "replacedValue" for the "value" element with attribute lang="en-US".
Unfortunately I have to do this for a XML attribute in a database which is typed which the following XML schema:
CREATE XML SCHEMA COLLECTION [dbo].[LocaleSchema] AS N'<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"><xsd:element name="translations"><xsd:complexType><xsd:complexContent><xsd:restriction base="xsd:anyType"><xsd:sequence minOccurs="0" maxOccurs="unbounded"><xsd:element name="value"><xsd:complexType><xsd:simpleContent><xsd:extension base="xsd:string"><xsd:attribute name="lang" type="language" /></xsd:extension></xsd:simpleContent></xsd:complexType></xsd:element></xsd:sequence></xsd:restriction></xsd:complexContent></xsd:complexType></xsd:element><xsd:simpleType name="language"><xsd:restriction base="xsd:string"><xsd:enumeration value="de-DE" /><xsd:enumeration value="en-US" /></xsd:restriction></xsd:simpleType></xsd:schema>'
For better readability afterwards only the XML schema pretty-printed:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="translations">
<xsd:complexType>
<xsd:complexContent>
<xsd:restriction base="xsd:anyType">
<xsd:sequence minOccurs="0" maxOccurs="unbounded">
<xsd:element name="value">
<xsd:complexType>
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="lang" type="language" />
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:restriction>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:simpleType name="language">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="de-DE" />
<xsd:enumeration value="en-US" />
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
As you can see here the "value" XML element is a complex type. According to the documentation the modify() function is only valid for simple types. (besides also the text() function is only valid for simple types)
So afterwards the SQL statements from above for the typed content - which causes an error when trying to modify:
declare #X xml (CONTENT [dbo].[LocaleSchema])=
'<translations>
<value lang="en-US">example</value>
<value lang="de-DE">Beispiel</value>
</translations>';
set #X.modify('replace value of (/translations/value[#lang="en-US"]/text())[1] with "replacedValue"');
Is there a suggestion to work around? Or any other possibility to change the XML attribute? (I need to use this in an UPDATE statement in real life of course)
Thank you in advance!
This works...
CREATE XML SCHEMA COLLECTION [dbo].[LocaleSchema] AS N'<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"><xsd:element name="translations"><xsd:complexType><xsd:complexContent><xsd:restriction base="xsd:anyType"><xsd:sequence minOccurs="0" maxOccurs="unbounded"><xsd:element name="value"><xsd:complexType><xsd:simpleContent><xsd:extension base="xsd:string"><xsd:attribute name="lang" type="language" /></xsd:extension></xsd:simpleContent></xsd:complexType></xsd:element></xsd:sequence></xsd:restriction></xsd:complexContent></xsd:complexType></xsd:element><xsd:simpleType name="language"><xsd:restriction base="xsd:string"><xsd:enumeration value="de-DE" /><xsd:enumeration value="en-US" /></xsd:restriction></xsd:simpleType></xsd:schema>';
GO
declare #X xml (CONTENT [dbo].[LocaleSchema])=
'<translations>
<value lang="en-US">example</value>
<value lang="de-DE">Beispiel</value>
</translations>';
set #X.modify('replace value of (/translations/value[#lang="en-US"])[1] with "replacedValue"');
SELECT #x;
GO
--clean up
--DROP XML SCHEMA COLLECTION dbo.LocaleSchema;

Import 'xml' into Sql Server

I have a file that is structured like so:
<?xml version="1.0" encoding="UTF-8"?>
<EventSchedule>
<Event Uid="2" Type="Main Event">
<IsFixed>True</IsFixed>
<EventKind>MainEvent</EventKind>
<Fields>
<Parameter Name="Type" Value="TV_Show"/>
<Parameter Name="Name" Value="The Muppets"/>
<Parameter Name="Duration" Value="00:30:00"/>
</Fields>
</Event>
<Event>
...and so on
</Event>
</EventSchedule>
I'm not entirely sure if it is valid XML, however I need to import it into SQL Server but everything I try doesn't seem to work.
Please could anyone point me in the right direction either with some example code or a recommendation on which method to use?
I'd ideally like to get the raw data into a flat table, along the lines of:
Name | Type | Duration | EventKind
The Muppets | TV_Show | 00:30:00 | MainEvent
Finally this is coming from fairly large files and I will need to import the regularly.
Thanks, pugu
Try this:
DECLARE #XML XML = '<EventSchedule>
<Event Uid="2" Type="Main Event">
<IsFixed>True</IsFixed>
<EventKind>MainEvent</EventKind>
<Fields>
<Parameter Name="Type" Value="TV_Show"/>
<Parameter Name="Name" Value="The Muppets"/>
<Parameter Name="Duration" Value="00:30:00"/>
</Fields>
</Event>
<Event Uid="3" Type="Secondary Event">
<IsFixed>True</IsFixed>
<EventKind>SecondaryEvent</EventKind>
<Fields>
<Parameter Name="Type" Value="TV_Show"/>
<Parameter Name="Name" Value="The Muppets II"/>
<Parameter Name="Duration" Value="00:30:00"/>
</Fields>
</Event>
</EventSchedule>'
SELECT
EventUID = Events.value('#Uid', 'int'),
EventType = Events.value('#Type', 'varchar(20)'),
EventIsFixed =Events.value('(IsFixed)[1]', 'varchar(20)'),
EventKind =Events.value('(EventKind)[1]', 'varchar(20)')
FROM
#XML.nodes('/EventSchedule/Event') AS XTbl(Events)
Gives me an output of:
And of course, you can easily do an
INSERT INTO dbo.YourTable(EventUID, EventType, EventIsFixed, EventKind)
SELECT
......
to insert that data into a relational table.
Update: assuming you have your XML in files - you can use this code to load the XML file into an XML variable in SQL Server:
DECLARE #XmlFile XML
SELECT #XmlFile = BulkColumn
FROM OPENROWSET(BULK 'path-to-your-XML-file', SINGLE_BLOB) x;
and then use the above code snippet to parse the XML.
Update #2: if you need the parameters, too - use this XQuery statement:
SELECT
EventUID = Events.value('#Uid', 'int'),
EventType = Events.value('#Type', 'varchar(20)'),
EventIsFixed = Events.value('(IsFixed)[1]', 'varchar(20)'),
EventKind = Events.value('(EventKind)[1]', 'varchar(20)'),
ParameterType = Events.value('(Fields/Parameter[#Name="Type"]/#Value)[1]', 'varchar(20)'),
ParameterName = Events.value('(Fields/Parameter[#Name="Name"]/#Value)[1]', 'varchar(20)'),
ParameterDuration = Events.value('(Fields/Parameter[#Name="Duration"]/#Value)[1]', 'varchar(20)')
FROM
#XML.nodes('/EventSchedule/Event') AS XTbl(Events)
Results in:
You do it by creating a destination table, then a schema mapping file that maps the xml elements to table columns.
Yours might look a bit like this:
create table event (
Type nvarchar(50),
Name nvarchar(50),
Duration nvarchar(50))
and this:
<?xml version="1.0" ?>
<Schema xmlns="urn:schemas-microsoft-com:xml-data"
xmlns:dt="urn:schemas-microsoft-com:xml:datatypes"
xmlns:sql="urn:schemas-microsoft-com:xml-sql" >
<ElementType name="Type" dt:type="string" />
<ElementType name="Name" dt:type="string" />
<ElementType name="Duration" dt:type="string" />
<ElementType name="EventSchedule" sql:is-constant="1">
<element type="Event" />
</ElementType>
<ElementType name="Event" sql:relation="Event">
<element type="Type" sql:field="Type" />
<element type="Name" sql:field="Name" />
<element type="Duration" sql:field="Duration" />
</ElementType>
</Schema>
Then you can load your XML into your table using the XML bulk loader.
http://support.microsoft.com/kb/316005
If you need to do it without XML variable (from string in table-valued function)
SELECT
--myTempTable.XmlCol.value('.', 'varchar(36)') AS val
myTempTable.XmlCol.query('./ID').value('.', 'varchar(36)') AS ID
,myTempTable.XmlCol.query('./Name').value('.', 'nvarchar(MAX)') AS Name
,myTempTable.XmlCol.query('./RFC').value('.', 'nvarchar(MAX)') AS RFC
,myTempTable.XmlCol.query('./Text').value('.', 'nvarchar(MAX)') AS Text
,myTempTable.XmlCol.query('./Desc').value('.', 'nvarchar(MAX)') AS Description
--,myTempTable.XmlCol.value('(Desc)[1]', 'nvarchar(MAX)') AS DescMeth2
FROM
(
SELECT
CAST('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<data-set>
<record>
<ID>1</ID>
<Name>A</Name>
<RFC>RFC 1035[1]</RFC>
<Text>Address record</Text>
<Desc>Returns a 32-bit IPv4 address, most commonly used to map hostnames to an IP address of the host, but it is also used for DNSBLs, storing subnet masks in RFC 1101, etc.</Desc>
</record>
<record>
<ID>2</ID>
<Name>NS</Name>
<RFC>RFC 1035[1]</RFC>
<Text>Name server record</Text>
<Desc>Delegates a DNS zone to use the given authoritative name servers</Desc>
</record>
</data-set>
' AS xml) AS RawXml
) AS b
--CROSS APPLY b.RawXml.nodes('//record/ID') myTempTable(XmlCol);
CROSS APPLY b.RawXml.nodes('//record') myTempTable(XmlCol);
Or from file:
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[tfu_RPT_SEL_XmlData]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
DROP FUNCTION [dbo].[tfu_RPT_SEL_XmlData]
GO
CREATE FUNCTION [dbo].[tfu_RPT_SEL_XmlData]
(
#in_language varchar(10)
,#in_reportingDate datetime
)
RETURNS TABLE
AS
RETURN
(
SELECT
--myTempTable.XmlCol.value('.', 'varchar(36)') AS val
myTempTable.XmlCol.query('./ID').value('.', 'varchar(36)') AS ID
,myTempTable.XmlCol.query('./Name').value('.', 'nvarchar(MAX)') AS Name
,myTempTable.XmlCol.query('./RFC').value('.', 'nvarchar(MAX)') AS RFC
,myTempTable.XmlCol.query('./Text').value('.', 'nvarchar(MAX)') AS Text
,myTempTable.XmlCol.query('./Desc').value('.', 'nvarchar(MAX)') AS Description
FROM
(
SELECT CONVERT(XML, BulkColumn) AS RawXml
FROM OPENROWSET(BULK 'D:\username\Desktop\MyData.xml', SINGLE_BLOB) AS MandatoryRowSetName
) AS b
CROSS APPLY b.RawXml.nodes('//record') myTempTable(XmlCol)
)
GO
SELECT * FROM tfu_RPT_SEL_XmlData('DE', CURRENT_TIMESTAMP);
e.g.
DECLARE #bla varchar(MAX)
SET #bla = 'BED40DFC-F468-46DD-8017-00EF2FA3E4A4,64B59FC5-3F4D-4B0E-9A48-01F3D4F220B0,A611A108-97CA-42F3-A2E1-057165339719,E72D95EA-578F-45FC-88E5-075F66FD726C'
-- http://stackoverflow.com/questions/14712864/how-to-query-values-from-xml-nodes
SELECT
x.XmlCol.value('.', 'varchar(36)') AS val
FROM
(
SELECT
CAST('<e>' + REPLACE(#bla, ',', '</e><e>') + '</e>' AS xml) AS RawXml
) AS b
CROSS APPLY b.RawXml.nodes('e') x(XmlCol);
So you can have a function like
SELECT * FROM MyTable
WHERE UID IN
(
SELECT
x.XmlCol.value('.', 'varchar(36)') AS val
FROM
(
SELECT
CAST('<e>' + REPLACE(#bla, ',', '</e><e>') + '</e>' AS xml) AS RawXml
) AS b
CROSS APPLY b.RawXml.nodes('e') x(XmlCol)
)
If you're trying to import your XML as a "pure" XML field you should create a table like this (obviously with many other fields as you want):
CREATE TABLE [dbo].[TableXML](
[ID] [int] IDENTITY(1,1) NOT NULL,
[XmlContent] [xml] NOT NULL -- specify [xml] type
)
Then you can easily insert your XML as a string:
INSERT INTO [dbo].[TableXML]
([XmlContent])
VALUES
('<?xml version="1.0" encoding="UTF-8"?>
<EventSchedule>
<Event Uid="2" Type="Main Event">
<IsFixed>True</IsFixed>
<EventKind>MainEvent</EventKind>
<Fields>
<Parameter Name="Type" Value="TV_Show"/>
<Parameter Name="Name" Value="The Muppets"/>
<Parameter Name="Duration" Value="00:30:00"/>
</Fields>
</Event>
</EventSchedule>')
Then to query start from MSDN t-SQL XML
If you prefer store it as string use a varchar(max) in place of [XML] column type and the same insert. But if you like to query easily I suggest [XML] type. With the flat string approach you need a lot of work unless you will implement some application code to parse it and store in a flat table.
A good approach could be an XML storage in a "compress" TABLE and a VIEW for data retrieve with the flat field disposition.
How to load the below XML data into the SQL
<?xml version="1.0" encoding="utf-8"?>
<DataTable xmlns="SmarttraceWS">
<xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:MainDataTable="ActivityRecords" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="ActivityRecords">
<xs:complexType>
<xs:sequence>
<xs:element name="ReferenceID" type="xs:long" minOccurs="0" />
<xs:element name="IMEI" type="xs:string" minOccurs="0" />
<xs:element name="Asset" type="xs:string" minOccurs="0" />
<xs:element name="Driver" type="xs:string" minOccurs="0" />
<xs:element name="DateTime" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
<diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
<DocumentElement xmlns="">
<ActivityRecords diffgr:id="ActivityRecords1" msdata:rowOrder="0">
<ReferenceID>2620443016</ReferenceID>
<IMEI>013795001360346</IMEI>
<Asset>L-93745</Asset>
<Driver>N/A</Driver>
<DateTime>2019-10-14 12:00:35</DateTime>
</ActivityRecords>
</DocumentElement>
</diffgr:diffgram>
</DataTable>

How to show table relationships in xml schema derived from tsql query?

I found this tsql query that shows the xml schema of a table and it works very well.
SELECT * FROM TableA
FOR XML AUTO, XMLSCHEMA
I am now attempting to show the relationship between tables via this query. I am not sure if this is possible. I have mocked up several test tables and I have not had any luck. Basically, I am creating a one to many relationship between tableA and tableB, then in the xml schema it would show tableA as a parent and tableB would be a child within the schema.
This is what I have been running. :
SELECT * FROM TableA,
dbo.TableB
FOR XML AUTO, XMLSCHEMA
Here is an example xml schema file that I am getting from the above query.
<xsd:schema targetNamespace="urn:schemas-microsoft-com:sql:SqlRowSet7" xmlns:schema="urn:schemas-microsoft-com:sql:SqlRowSet7" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes" elementFormDefault="qualified">
<xsd:import namespace="http://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="http://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd" />
<xsd:element name="TableA">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="columnA" type="sqltypes:int" />
<xsd:element name="columnB">
<xsd:simpleType>
<xsd:restriction base="sqltypes:varchar" sqltypes:localeId="1033" sqltypes:sqlCompareOptions="BinarySort">
<xsd:maxLength value="50" />
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element ref="schema:dbo.tylersTestTable2" minOccurs="0" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="TableB">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="columnA" type="sqltypes:int" />
<xsd:element name="columnB">
<xsd:simpleType>
<xsd:restriction base="sqltypes:varchar" sqltypes:localeId="1033" sqltypes:sqlCompareOptions="BinarySort">
<xsd:maxLength value="50" />
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="fkToTableA" type="sqltypes:int" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
As you can see it is displaying the tables as equal levels within the schema and not really displaying a parent child relationship.
I am kind of at a loss here as I am no dba, but I have to do this for a ton of tables and I don't want to have to write them all by hand.
Any ideas on this one?
Tables in TSQL do not have true parent-child relationships. Each table is at the same level and foreign key relationships may cause constraints on data in one or both tables. Logically, one table may be a parent and one a child, but in no way does that mean they are a physical hierarchy. You may be able to generate XML like you're asking for with a modeling tool like ERwin that interprets the physical model into a logical one but TSQL really only sees the physical model.

Resources