понедельник, 5 сентября 2011 г.

XML Schema в SQL Server


Я уже как-то писал про то, что в SQL можно читать элементы XML прямо из столбца с соответствующим типом. Для того, чтобы SQL сервер контролировал правильность этого поля, используется специальный язык описания правил — XML Schema. Рассмотрим простейший пример такой схемы (сегодня все примеры для Microsoft SQL Server 2008):
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

    <xsd:complexType name="PointType">
     <xsd:attribute name="X" type="xsd:int" />
     <xsd:attribute name="Y" type="xsd:int" />
     <xsd:attribute name="Z" type="xsd:int" use="optional" />
    </xsd:complexType>

    <xsd:element name="Point" type="PointType" />
</xsd:schema>
Данная схема разрешает только XML следующих видов:
<Point X="100" Y="100" />
<!-- или -->
<Point X="100" Y="100" Z="500"/>
При этом атрибуты X и Y являются обязательными, а Z — опциональным. Для атрибутов допускается только тип int. В MS SQL Server создание подобной схемы будет выглядеть так:
CREATE XML SCHEMA COLLECTION test AS '
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

    <xsd:complexType name="PointType">
     <xsd:attribute name="X" type="xsd:int" />
     <xsd:attribute name="Y" type="xsd:int" />
     <xsd:attribute name="Z" type="xsd:int" use="optional" />
    </xsd:complexType>

    <xsd:element name="Point" type="PointType" />
</xsd:schema>
'
GO
Далее можно попробовать создать xml с данной схемой (ниже используется переменная для того, чтобы этот код можно было легко скопировать и попробовать, но тоже самое верно и для столбца в таблице):
-- объявляем переменную @xml с ранее созданной схемой test
DECLARE @xml xml(test)

-- заполняем тестовыми данными
SET @xml='<Point X="10" Y="10" />'

-- делаем выборку
SELECT @xml.value('(/Point/@X)[1]','int'), @xml.value('(/Point/@Y)[1]','int')
При попытке записать невалидные данные SQL Server выдаст ошибку:
-- пробуем задать невалидный XML
SET @xml='<WrongPoint X="10" Y="10" />'

-- получаем ошибку
-- XML Validation: Declaration not found for element 'WrongPoint'. Location: /*:WrongPoint[1]
Таким образом, наличие схемы гарантирует валидность данных и нет необходимости обрабатывать возможные ошибки самостоятельно.

Ссылки:

Комментировать в ВКонтакте