XML в Oracle - это очень простоВладимир Пржиялковский
Оглавление
ВведениеТип XMLTYPE появился в Oracle в версии 9.0. До этого наиболее подходящим для хранения документов в формате XML был тип CLOB (и менее подходящим - тип VARCHAR2, ограниченный максимумом 4000 знаков). Сам по себе объектный, новый тип XMLTYPE технически может храниться либо по-прежнему в виде CLOB, либо в виде объекта (начиная с версии 9.2). И еще одно замечание: несмотря на то, что технологии XML и Java идут "рука об руку", рамки приводимых ниже примеров не требуют от вашей БД установленных возможностей Java. В этой заметке рассмотрены только логические стороны использования XML в Oracle безотносительно к техническим свойствам хранения и доступа. Простой примерCREATE TABLE books INSERT INTO books VALUES SET long 1000 SELECT id, description FROM books; SELECT id, b.description.XMLDATA FROM books b; XMLDATA - специально созданный для XMLTYPE "псевдостолбец". XMLTYPE - тип XMLXMLTYPE дает возможность сообщить БД, что заносимый текст - это не просто строка, а строка документа XML. Следующая попытка приведет к ошибке: INSERT INTO books VALUES (101, XMLTYPE('<cover><title></title>')); С дугой стороны, Oracle поймет правильно составленные директивы XML и встроенное в текст описание DTD: INSERT INTO books VALUES Убедитесь в этом сами, что Oracle действительно соотносит описание DTD самому тексту документа! Для выборки можно использовать специально придуманные для XMLTYPE функции. Так, функция EXTRACTVALUE извлекает значения элемента из документа XML: SELECT id, EXTRACTVALUE(description, '/cover/title') Функция EXISTSNODE дает возможность использовать в SQL условие отбора XPath (язык отбора, принятый в технологиях XML): SELECT id, b.description.XMLDATA XMLTYPE - объектный тип OracleДоказательством утверждения в заголовке служит создание следующей таблицы объектов типа XMLTYPE, "таблицы документов XML": CREATE TABLE xbooks OF XMLTYPE; Работать с ними можно, как и с XML-атрибутом в обычной таблице: INSERT INTO xbooks VALUES INSERT INTO xbooks VALUES В первом случае объект XML создается с помощью конструктора, а во втором, к тому же, используется оператор NEW. Последний применяется в Oracle для работы с объектами, однако его использование носит лишь рекомендательный характер, так как в SQL он ничего содержательного не дает. Далее: SELECT * FROM xbooks; SELECT VALUE(x) FROM xbooks x; SELECT XMLDATA FROM xbooks; Так же как для таблиц объектов прочих типов, элементы таблицы объектов XML имеют ссылки, то есть позволяют ссылаться на себя через REF в других типах и таблицах: SELECT REF(x) FROM xbooks x; SELECT DEREF(REF(x)) FROM xbooks x; У этого типа нет свойств, но есть методы. В этом можно убедиться, сделав запрос от имени SYS: COLUMN text FORMAT A80 SELECT text Исследование каталога rdbms/admin позволяет обнаружить и исходное описание этого типа (но не его тела!) в файле dbmsxmlt.sql. К сожалению, в документации описания этих методов разбросаны по разным местам, не всегда последовательны и ясны. Так, например, EXTRACT и EXISTSNODE (о последней речь шла выше), возведены в ранг функций SQL, то есть описаны в книжке документации по SQL в разделе "Функции", в то время как из предыдущего запроса к словарю-справочнику следует, что это методы. О том же говорит синтаксис употребления. Для EXISTSNODE пример уже приводился, а для EXTRACT он может выглядеть так: SELECT b.description.EXTRACT('/cover/title') FROM books b; (Сравните с примером использования функции EXTRACTVALUE выше). Вот некоторые другие примеры методов XMLTYPE: SELECT b.description.GETCLOBVAL() FROM books b; SELECT b.description.GETSTRINGVAL() FROM books b; SELECT b.description.GETROOTELEMENT() FROM books b; Обратите внимание, что некоторые методы XMLTYPE, например TOOBJECT, могут использоваться только процедурно, так как сами исполнены в виде процедур, а не функций. Правда, объектность типа XMLTYPE реализована не в полной степени. Так, попытка создать в таблице столбец из коллекции документов XML (вложенной таблицы или массива VARRAY) в версии 9.2 терпит неудачу. Это относится только к БД; в PL/SQL этих проблем не возникает: SQL> declare type xml_nt is table of xmltype index by varchar2(10); PL/SQL procedure successfully completed. Взаимные преобразования табличного вида и XMLTYPEСвязь двух форм описания данных - табличной и XML - достигается не одною только возможностью создавать в таблицах столбец типа XMLTYPE. Возможно преобразование данных из одного вида в другой, благодаря чему исходный формат хранения данных может оказаться не столь существенен. Преобразование из XMLTYPE в табличную формуДля преобразования данных типа XMLTYPE в обычный табличный вид можно использовать функции SQL и методы XMLTYPE, в первую очередь упоминавшуюся метод-функцию EXTRACT: COLUMN xdoc FORMAT A80 SELECT ROWNUM, id, b.description.EXTRACT('/cover/author') xdoc Обратите внимание на возможность и способ обработки нескольких авторов в XML элементах <author>. Использование функции SQL EXTRACTVALUE, в свою очередь, оставляет возможность отбора не более одного элемента XML для формирования каждой строки результата SELECT, но зато безболезненно убирает обрамляющие значение элемента XML метки: SELECT id, EXTRACTVALUE(b.description.EXTRACT('/cover/title'), '/title') xdoc То же самое можно записать проще, что уже демонстрировалось в начале статьи. Преобразование из табличной формы в XMLTYPEДля обратного преобразования удобно воспользоваться функциями, объединенными в стандарте SQL:2003 названием SQL/XML. В версии Oracle 9.2 реализованы следующие (не все) функции из этого стандартного набора: - XMLElement Вот некоторые примеры использования в схеме SCOTT: SELECT XMLELEMENT("Employee", ename) FROM emp; SELECT XMLELEMENT("Employee", Обратите внимание, что в результатах выдаются поля типа XMLTYPE: CREATE TABLE xtable (n) AS SELECT XMLELEMENT("Name", ename) FROM emp; DESCRIBE xtable Следующий пример - агрегирующей функции XMLAGG, допускающей использование в запросах с группировкой GROUP BY, подобно тому, как агрегирующие функции MIN, AVG и другие применяются для обычных данных, а не XMLTYPE: SET LONG 2000 SELECT XMLELEMENT("department", XMLATTRIBUTES(deptno AS "no")), Интересно, что последний запрос допускает создания на своей основе выводимой таблицы, но не базовой: CREATE VIEW xview (a, b) AS (срабатывает) CREATE TABLE xtable (a, b) AS (ошибка!) Это объясняется тем, что столбцы A и B в обоих случаях Oracle пытается создавать как XMLTYPE, а наши данные таковы, что в столбце B содержатся, строго говоря, некорректные строки XML, например <employee>CLARK</employee><employee>KING</employee> .... Однако в случае выводимой таблицы Oracle смотрит на это сквозь пальцы, а в случае базовой - нет. Возможно, это есть следствие определенной недоработанности некоторых областей технологий XML в Oracle, что вызвано чересчур быстрыми темпами развития этих технологий. |