How to Add an Inline Schema When Using FOR XML in SQL Server

When using the FOR XML clause in a query in SQL Server, we can generate an XML document either with or without an inline schema.

To generate it with an inline XSD schema simply include the XMLSCHEMA argument. We can alternatively include the namespace if we want to specify a particular namespace.

At the time of writing, the XMLSCHEMA argument is only available when in either AUTO or RAW mode.

Example

Here’s an example to demonstrate:

SELECT
    PetId,
    DOB
FROM Pets
ORDER BY PetId
FOR XML AUTO, XMLSCHEMA;

Result:

<schema targetNamespace="urn:schemas-microsoft-com:sql:SqlRowSet4" xmlns:schema="urn:schemas-microsoft-com:sql:SqlRowSet4" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes" elementFormDefault="qualified">
	<import namespace="http://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="http://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd" />
	<element name="Pets">
		<complexType>
			<attribute name="PetId" type="sqltypes:int" use="required" />
			<attribute name="DOB" type="sqltypes:date" />
		</complexType>
	</element>
</schema>
<Pets xmlns="urn:schemas-microsoft-com:sql:SqlRowSet4" PetId="1" DOB="2020-11-20" />
<Pets xmlns="urn:schemas-microsoft-com:sql:SqlRowSet4" PetId="2" />
<Pets xmlns="urn:schemas-microsoft-com:sql:SqlRowSet4" PetId="3" DOB="2018-10-01" />

Specify the Namespace

The target namespace of the schema document that describes the shape of the FOR XML result contains a fixed portion and a numeric portion that increments automatically. This numeric portion increments each time we run the query. We can see this in the previous example, where the namespace ends with SqlRowSet4. The 4 is there, because I ran it four times. The next time I run it, it will increment to SqlRowSet5, and so on.

If this isn’t desirable, we can change it so that it uses a fixed namespace.

SELECT
    PetId,
    DOB
FROM Pets
ORDER BY PetId
FOR XML AUTO, XMLSCHEMA ('urn:schemas-microsoft-com:sql:SqlRowSet1');

Result:

<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">
	<import namespace="http://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="http://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd" />
	<element name="Pets">
		<complexType>
			<attribute name="PetId" type="sqltypes:int" use="required" />
			<attribute name="DOB" type="sqltypes:date" />
		</complexType>
	</element>
</schema>
<Pets xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1" PetId="1" DOB="2020-11-20" />
<Pets xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1" PetId="2" />
<Pets xmlns="urn:schemas-microsoft-com:sql:SqlRowSet1" PetId="3" DOB="2018-10-01" />

Using the Wrong Mode

As mentioned, the XMLSCHEMA argument is only available when in either AUTO or RAW mode at the time of writing. In the above examples, I ran it in AUTO mode.

Here’s what happens when I try to use XMLSCHEMA in PATH mode:

SELECT
    PetId,
    DOB
FROM Pets
ORDER BY PetId
FOR XML PATH, XMLSCHEMA;

Result:

Msg 6855, Level 16, State 1, Line 1
Inline schema is not supported with FOR XML PATH.

I actually get a different error when I use EXPLICIT mode:

SELECT
    1 AS Tag,
    NULL AS Parent,
    p.PetId AS [Pet!1!PetId],
    NULL AS [Details!2!PetName],
    NULL AS [Details!2!PetType]
FROM Pets p 
    INNER JOIN PetTypes pt ON p.PetTypeId = pt.PetTypeId
UNION ALL
SELECT
    2 AS Tag,
    1 AS Parent,
    p.PetId,
    p.PetName,
    pt.PetType
FROM Pets p 
    INNER JOIN PetTypes pt ON p.PetTypeId = pt.PetTypeId
ORDER BY [Pet!1!PetId], [Details!2!PetName]
FOR XML EXPLICIT, XMLSCHEMA;

Result:

Msg 3625, Level 16, State 17, Line 1
'Inline XSD for FOR XML EXPLICIT' is not yet implemented.

This error implies that XMLSCHEMA may be supported in future versions of SQL Server.

XDR Schemas

There’s also an XMLDATA directive that generates an XDR schema when using FOR XML. However, this directive is now deprecated, and Microsoft recommends that we use the XMLSCHEMA method above.

More Information

See the Microsoft documentation for more information on generating an inline XSD schema in SQL Server.