Сейчас я хочу рассмотреть сценарий работы с данными в виде XML, которые могут храниться в базе данных. Современные серверы БД поддерживают, в разной степени, тип данных XML. Я буду приводить примеры в MySql, т. к. под рукой в данный момент есть только он. Например, у нас есть таблица xmltest:
CREATE TABLE `xmltest` ( `conf` varchar(500) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1Далее, будем считать, что в поле conf хранятся данные каждого пользователя системы следующего вида:
<Root> <CoreOptions> <Option type="str" value="test" /> </CoreOptions> <UserOptions> <Favorites> <Page id="1">http://www.codeatcpp.com</Page> <Page id="2">http://www.google.com</Page> <Page id="3">http://www.yandex.ru</Page> <Page id="4">http://www.stackoverflow.com</Page> </Favorites> </UserOptions> </Root>Итак, можно загрузить все данные пользователей и каждый конфиг разобрать своим любимым парсером XML, но что, если мы всего лишь хотим посмотреть сколько у каждого пользователя любимых сайтов? Это можно узнать за один SQL запрос используя язык XQuery+XPath:
SELECT ExtractValue(conf, 'count(/Root[1]/UserOptions[1]/Favorites[1]/Page)') FROM `xmltest`Этот запрос для каждого пользователя выдаст количество элементов Page в поле conf. Поскольку в XML элементы не уникальны и могут повторятся, то указываем в квадратных скобках, что нужен первый по порядку элемент. Если это не указать, то запрос вернет набор элементов, как в случае с Page.
Если мы хотим получить атрибут элемента, то показываем это символом @:
SELECT ExtractValue(conf, '/Root[1]/UserOptions[1]/Favorites[1]/Page[1]/@id') FROM `xmltest`Такой запрос выдаст идентификатор первой страницы для каждого пользователя.
Стоит отметить, что для разных реализаций SQL синтаксис запроса будет отличаться, например, в MS SQL Server последний запрос будет выглядеть так:
SELECT conf.value('/Root[1]/UserOptions[1]/Favorites[1]/Page[1]/@id', 'int') FROM xmltest
Поля XML можно не только выводить, но и использовать в условиях поиска, например:
SELECT ExtractValue(conf, '/Root[1]/CoreOptions[1]/Option[1]/@value') FROM `xmltest` WHERE ExtractValue(conf, 'count(/Root[1]/UserOptions[1]/Favorites[1]/Page)') > 0Такой запрос выдаст параметр Option из раздела CoreOptions для всех пользователей, у которых есть закладки.
В такой маленькой статье невозможно рассмотреть все возможности работы с XML в SQL запросах, поэтому даю список ресурсов, с которыми стоит познакомиться:
- Методы типа данных XML в MS SQL Server.
- XML функции сервера MySQL.
- xpathtester.com — сайт, где можно проверить свои XPath запросы.
- Вопросы и ответы по использованию XML в SQL запросах.