DevX HomePage

Kiss the Middle-tier Goodbye with SQL Server Yukon

Yukon's new XML support features cut out the middleman and allow you to deal with your data directly on the database tier. Learn how to use these features to improve your database app's performance and design.
uch of the buzz surrounding the release of SQL Server Yukon seems to be about its new integration with the CLR. However, there are plenty of other worthwhile features in this lastest release—and at least one of them can make your database application programming whole a lot easier. Besides CLR integration, Yukon also offers three new XML support features that effectively eliminate the use of middle-tier components.

With SQL Server 2000, you needed datatypes like varchar or text to store XML data. Furthermore, there was no chance to query XML data directly on the database tier. You read your XML data in strings and passed them to the middle-tier components, which would then query against the XML data. The resulting XML was shown through the use of XSL transformations. Obviously, this was not a very elegant approach.

Yukon's three new XML support features allow you to interact directly with your XML data.

XML Datatypes
One way to think about the new datatype (xml) is to see it as similar to datatypes like varchar, datetime, or float. You can use it to declare columns, parameters, or variables. This new datatype allows you to:




Typed or Untyped
What's the difference bwteen storing data in typed or untyped form? First of all, XML data is stored by default in untyped form—without the use of an XML schema. This XML data must be well-formed. To store XML data in a typed form, you must reference an XML schema within the declaration of your columns, parameters, and variables. The following code shows how to use an untyped XML datatype:


-- Creating a new XML datatype variable
DECLARE @xml

-- Creating a new table with a xml datatype column
CREATE TABLE MyTable(ID int primary key, 
   MyXMLColumn xml)

-- Creating a stored procedure with an xml datatype
-- parameter
CREATE PROCEDURE MyStoredProcedure(ID int, 
   MyXMLValue xml)
AS
...

-- Creating a new table with a xml datatype column 
-- with a default value
CREATE TABLE MyTable(ID int primary key, 
   MyXMLColumn xml default
   '<Customer></Customer>")
To use a typed XML datatype, reference an XML schema during the declaration of the datatype. You must register the XML schema inside of Yukon in order to reference it. During this registration process, the XML schema is analyzed and all found types are imported and registered in Yukon's metasystem. Apparently, XML schemas are not simply stored as text blobs in Yukon. Because of this, it's impossible to restore the XML schema to its original state.

Luckily, Yukon provides a function to recreate the XML schema from the metadata. However, keep in mind that annotations, like comments, can't be reproduced because they are not stored in the metasystem. To register a XML schema within Yukon, use the new T-SQL statement CREATE XMLSCHEMA:


CREATE XMLSCHEMA
'<?xml-version="1.0" encoding="utf-8" ?>
<xs:schema targetNamespace=
  "http://www.csharp.at/Conferences/2004/02/ASPKonferenz" 
   elementFormDefault="qualified" 
   xmlns"http://www.csharp.at/Conferences/
   2004/02/ASPKonferenz" 
   xmlns:xs="http://www.w3.org/2001/XMLSchema" 
   xmlns:NS="http://www.csharp.at/Conferences/
   2004/02/ASPKonferenz">
   <xs:element name="Customer">
      <xs:complexType>
         <xs:attribute name="CustomerID" 
            type="xs:string" use="required" />
         <xs:attribute name="State" 
            type="xs:string" use="optional" />
         <xs:attribute name="Type" 
            type="xs:string" use="optional" >/
      </xs:complexType>
   </xs:element>
</xs:schema>'
After its registered, the XML schema can then be referenced through the target namespace http://www.csharp.at/Conferences/2004/02/ASPKonferenz.

For the new XML schema, a new record is inserted into the system table sys.xml_namespaces. This new record consists of the namespace name and a unique ID assigned to that namespace. With this ID, relations to other system tables are established. For each new type within the XML schema, a new record in the system table sys.xml_components is inserted. In the example, a new record was created for the <Customer> element and for each attribute as well.

With the system function xml_schema_namespace, Yukon allows you to regenerate the XML schema out of the stored metadata. You can call this function from a SELECT statement. As a parameter, you pass in the namespace name of the registered XML schema that should be regenerated:


SELECT xml_schema_namespace 
(N'http://www.csharp.at/Conferences/2004/02/ASPKonferenz)
To delete an already registered XML schema, use the T-SQL statement DROP XMLSCHEMA. Remember, the deleted XML schema must have no references to other objects (like tables or stored procedures):

DROP XMLSCHEMA NAMESPACE
'http://www.csharp.at/Conferences/2004/02/ASPKonferenz'
Here's how to create a typed XML datatype column within a table:

CREATE TABLE Customers
(
   ID int primary key,
   CustomerDocument xml 
      ('http://www.csharp.at/Conferences/
      2004/02/ASPKonferenz')
)
As you can see, the target namespace of the referencing XML schema must be provided during the creation of the new table.




Loading the XML Datatype
How do you load XML data into the new XML datatype? With Yukon, you can convert string data to XML data implicitly or explicitly by using the T-SQL functions CAST and CONVERT. Take a look:


INSERT INTO Customers (ID, CustomerDocument)
VALUES
(
   1, 
   '<Customer 
      xmlns="http://www.csharp.at/Conferences/
      2004/02/ASPKonferenz" 
      CustomerID="ALFKI" State="DE" Type="ISV">
      Alfreds Futterkiste
   </Customer>'
)

INSERT INTO Customers(ID, CustomerDocument)
VALUES
(
   2, 
   CAST('<Customer xmlns="http://www.csharp.at/
      Conferences/2004/02/ASPKonferenz" 
      CustomerID="MSFT" State="WA" Type="ISV">
      Microsoft Corporation
   </Customer>' AS xml)
)

INSERT INTO Customers(ID, CustomerDocument)
VALUES
(
   3, 
   CONVERT(xml, '<Customer xmlns="http://www.csharp.at/
      Conferences/2004/02/ASPKonferenz" 
      CustomerID="TT" State="AT" Type="ISV">
      TechTalk
   </Customer>')
)
You need to provide the target namespace in order to insert XML data to a typed XML datatype. Without the the target namespace, Yukon raises an exception and the data won't be inserted. This guarantees that all inserted XML data is validated and matches the provided XML schema.




Creating Constraints
You can also create constraints during the creation of a table with the use of the T-SQL function check:


CREATE TABLE Customers
(
   Col1 int primary key,
   Col2 xml check(
      Col2::exist('/Customer/@CustomerID' = 1)
)

-- The following insert operation succeeds
INSERT INTO Customers (Col1, Col2)
VALUES (1, '<Customer CustomerID="ALFKI" />')

-- The following insert operation didnt succeeds
INSERT INTO Customers (Col1, Col2)
VALUES (2, '<Customer>Alfreds Futterkiste</Customer>')
You need to check the constraint in order to make sure that the attribute CustomerID exists in the inserted XML data. The following code shows the creation of a constraint that verifies that the column CustomerID has the same value as the attribute CustomerID of the XML element <Customer>S:

CREATE TABLE Customers
(
   CustomerID int primary key,
   CustomerDocument xml,
   Constraint CustomerDocument_Check check
   (
      CustomerDocument::value('/Customer/@CustomerID', 
         'int') = CustomerID
   )
)

-- The following insert operation succeeds
INSERT INTO Customers (CustomerID, CustomerDocument)
VALUES (1, '<Customer CustomerID="1" />')

-- The following insert operation didn't succeeds
INSERT INTO Customers (CustomerID, CustomerDocument)
VALUES (2, '<Customer CustomerID="1" />')




XML Datatype Methods
With the help of these four functions, you can now embed XQuery statements directly into T-SQL code:




XQuery Extended
You can see that Yukon uses XQuery statements to produce some very powerful T-SQL code. But what if you want to reference another column or variable within your XQuery statement? The XQuery specification doesn't provide any support for this. For that reason, Microsoft has extended XQuery with two important functions:




The XML Data Modification Language (XML DML)
What if you want to alter XML data stored within Yukon? In SQL 200, you had to load the data from the database and pass it to a middle-tier component. The component then changed the data and wrote the changes back to the database.

Eliminating this step, Microsoft has extended the XQuery specification with the XML Data Modification Language. Based on XQuery, this language provides the necessary functionality to change XML data directly on the database tier.

Access the XML Data Modification Language using the XML data method modify(). The XML DML uses three keywords, insert, delete, and update.




Yukon's XML Limitations
As you've seen, SQL Server Yukon is first class for storing, querying, and updating XML Data. However, there are some some limitations when working with the new XML datatype and XML schemas:

  1. XML can't be casted to text or ntext.
  2. An XML column can't be part of a primary—or foreign key constraint.
  3. Only strings can be casted to XML.
  4. An XML column can't be used in a GROUP BY statement.
  5. An XML column can't be part of an index.
  6. It is only possible to create 32 XML columns per table.

The XML schema support in Yukon has the following limitations:

  1. Annotations (like comments) are not stored in the metasystem of Yukon.
  2. The XSD ID attribute is not supported.
  3. Default values can't be longer than 4000 unicode characters.
  4. XML schemas can't be converted to their origin state. Therefore, you need to manage XML schemas separately.

Even with these limitations, the ability to directly query and modify XML data on the database tier is a great step forward. If you work with XML data in your applications, it is well worth your time to investigate Yukon and find out whether you can benefit from these new features.

Klaus Aschenbrenner is CEO of the software company Solvion, which specializes in designing and programming enterprise applications based on the .NET Framework and Windows.NET. He has written articles for German magazines like DotNetPro and is a speaker at conferences. You can reach Klaus at Klaus.Aschenbrenner@techtalk.at.


DevX is a division of Jupitermedia Corporation
© Copyright 2007 Jupitermedia Corporation. All Rights Reserved. Legal Notices