Часть 1
В Oracle Database 10g у вас есть несколько возможностей хранения XML данных. Вы можете разделить XML документ на части и хранить данные в одной или нескольких реляционных таблицах, помещать XMLType-ы целиком в CLOB-ы или зарегистрировать XML схему и хранить их в объектно-ориентированой памяти на языке XML Schema, предназначеном для XMLType. Если нет необходимости корректировки XML-контента, также можно сохранить XML документы как внешние, используя механизм External Tables (внешних таблиц).
Эта глава дает содержит обзор способов хранения XML, доступных в Oracle Database 10g и демонстрирует различные варианты применения этих технологий. Даются примеры использования утилит Oracle SQL*Loader и XML SQL Utility (XSU) для загрузки XML документов в или XMLType-таблицу, или реляционную таблицу в Oracle Database 10g. Мы начнем с простейшего формата сохранения: CLOB XMLTypes (XMLType в CLOB).
Хранение XML документов в CLOB XMLTypes
Используя CLOB XMLType, XML документы хранятся как CLOB'ы c установкой XML интерфейсов, предоставляемых XMLType. Не смотря на то, что перед загрузкой данных можно опционально запустить любой XML процесс, например, ввод данных XML в XML схему или DTD, размещение CLOB XMLType не нуждается ни в каком XML процессе, за исключением проверки формальной правильности и разрешения существования.
Запрос и обновление CLOB XMLType
Хранение в виде CLOB XMLType наилучшим образом консервирует оригинальный формат XML документов и дает максимальную гибкость при развитии XML схемы.
Однако, хранение XML документов в CLOB XMLTypes приводит к дорогой избыточной обработке при запросе XML контента такими функциями, как XMLType.Extract() или XMLType.ExistsNode(), поскольку эти операции требуют во время обработки построения в оперативной памяти дерева XML DOM и выполнения функциональных Xpath оценок. Кроме того, любая операция обновления (update) может быть осуществлена только на уровне документа. Это означает, что вам необходимо обновлять весь XML документ после каждого даже незначительного изменения какого-либо XML элемента.
Поэтому, как правило, следует избегать использования XMLType функций при выполнении незначительных XML обновлений или запросов с задействованием Xpath при действиях с CLOB XMLTypes.
Вместо XPath-запросов к CLOB XMLTypes, Oracle Text обеспечивает поиск по всему тексту, поддерживая ограниченное множество [путей] XPaths. Эта функциональность позволяет выполнять ХРath запросы в XMLTypes, используя CONTEXT индекс, создаваемый Oracle Text, который является очень полезным и масштабируемым механизмом для приложений, что мы обсудим в главе 11 (“Searching XML Data”).
Действия с символьными кодировками в CLOB XMLTypes
Нужно знать, что когда XML документ хранится в Oracle Database, символьная перекодировка автоматически выполняется перед вводом данных, при этом по набору символов (character set – кодовая таблица), установленному в базе данных, конвертируются все текстовые данные, включая XML документы. Исключением является хранение типов данных BLOB, NCHAR и NCLOB.
Вследствие такого неявного преобразования набора символов, актуальная кодировка XML данных и декларируемая в прологе <?XML?> кодировка - не одно и то же. В нынешнем релизе Oracle Database 10g, XMLType API игнорирует декларируемую в прологе <?XML?> кодировку и предполагает, что XML данные хранятся в CLOB XMLTypes в кодировке базы данных. Следовательно, при загрузке клиентских XML данных необходимо убедиться, что конверсия кодов успешно выполнена.
Если XML документ изначально хранится в кодировке клиента, отличной от алфавита базы данных, то для того, чтобы гарантировать правильность конверсии из кодировки клиента в алфавит базы данных, необходимо установить переменную среды NLS_LANG, называющую кодовую таблицу клиента. Однако, если в переменной установлена такая же кодировка, как и набор символов базы данных, оригинальный текст в базе данных будет сохранен “как есть” без проверки правильности символов и конверсии. Другими словами, если переменная среды NLS_LANG не установлена или установлена неправильно, а XML документ имеет другую кодировку, чем база данных, в базе данных будет хранится просто мусор.
ЗАМЕЧАНИЕ
Если XML документ содержит символы, которые не включены в алфавит базы данных, то перед добавлением данных в CLOB XMLTypes вы получите ошибку Invalid Character. Возможным решением может служить использование NCLOB или BLOB для сохранения данных в базе данных и построение XML приложения среднего слоя или внешней PL/SQL процедуры, использющих XDK API для обработки XML данных.
Из-за конверсии алфавита может произойти конфликт между действующей кодировкой и кодировкой, декларируемой в прологе <?XML?>, при считывании XML данных из CLOB XMLTypes, во избежание чего следует создать реверсивную кодовую таблицу (reverse character set) или заменить декларирацию в <?XML?> прологе, чтобы сделать согласовать кодировки. Это важно, так как синтаксический анализатор XML использует первые 4 байта пролога <?XML?> для определения кодировки XML документов, и может быть определено только, что алфавит базируется на ASCII- или на EBCDIC- кодировках. Если он базируется на ASCII кодировке, то синтаксический анализатор XML может определить только, что он является UTF-8 или UTF-16. Иначе, это зависит от атрибутов кодирования в <?XML?>. Поэтому, если вы имеете XML документ не в UTF-8 или UTF-16 кодировках, то вы должны вставить правильную XML декларированную кодировку, чей алфавит используется, как показано ниже:
<?xml version="1.0"
encoding='Shift-JIS'?>
Хранение XML документов в XMLTypes на языке XML Schema
Для увеличения скорости ХРath запросов и незначительных обновлений XMLTypes, можно создать XMLTypes на основе XML Schema. Один из способов это сделать – надо сопоставить зарегистрированные XML схемы с столбцами или таблицами XMLType, используя XMLSCHEMA. Вы также можете создать XMLType таблицы, специфицируя аннотацию DEFAULT TABLE в зарегистрированных XML схемах.
Все эти подходы создают XMLTypes, базированные на XML Schema, где наборы объектно-реляционных таблиц/объектов соответствуют XML объектам, определенным в XML схеме. Единственное различие между созданием заданной по умолчанию(default) в процессе регистрации XML схемы таблицы и использованием ключевого слова (keyword) XMLSCHEMS состоит в том, что первое решение позволяет XML документам, соответствующим зарегистрированной XML схеме, находиться под управлением репозитория Oracle XML DB. Если имеет место поддержка репозитория XML DB, можно не только извлекать и обновлять XML в SQL, но также и управлять XML документами, хранящимися в репозитории XML DB, используя такие интерфейсные протоколы, как FTP и HTTP/WebDAV.
Регистрация XML схемы
Регистрация XML схемы определяется отображением XML-to-SQL и иерархической объектно-реляционной структурой для сохранения XML документов в базе данных Oracle. Мы посмотрим, как это жделается, используя созданных в 8-й главе пользователя по имени DEMO и папку WebDAV.
Первое, вам нужно скопировать XML схему для записей о клиентах, contact_simple.xsd, в папку /public WebDAV. Далее содержание этой схемы:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="Customer" type="CustomerType"/>
<xsd:complexType name="CustomerType">
<xsd:sequence>
<xsd:element name="NAME" type="xsd:string"/>
<xsd:element name="EMAIL" type="xsd:string"/>
<xsd:element name="ADDRESS" type="xsd:string"/>
<xsd:element name="PHONE" type="phoneType"/>
<xsd:element name="DESCRIPTION" type="contentType"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="ContentType" mixed="true">
<xsd:sequence>
<xsd:any minOccurs="0" maxOccurs="unbounded"
processContents="skip"/>
</xsd:sequence>
</xsd:complexType>
<xsd:simpleType name="phoneType">
<xsd:restriction base="xsd:string">
<xsd:pattern value="\(\d{3}\)\d{3}-\d{4}"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
Для регистрации этой XML схемы в XML DB можно применить следующую PL/SQL процедуру:
ALTER SESSION SET EVENTS='31098 trace name context forever';
BEGIN
DBMS_XMLSCHEMA.registerURI(
'http://localhost:8080/public/contact_simple.xsd',
'/public/contact_simple.xsd',
LOCAL=>TRUE, GENTYPES=>TRUE, GENBEAN=>FALSE,
GENTABLES=>TRUE);
END;
ЗАМЕЧАНИЕ
Для использования команды ALTER SESSION вам нужно зарегистрироваться как SYS и предоставлять привилегии ALTER SESSION пользователю DEMO, используя команду “GRANT ALTER SESSION TO DEMO”. Иначе вы получите сообщение об ошибке ORA-01031: Insufficient Privileges (Недостаточнопривилегий).
В функции DBMS_XMLSCHEMA.registerURI() первый параметр -
это схема URI, http://localhost:8080/public/contact_simple.xsd, которая уникально
идентифицирует зарегистрированную XML схему в XML DB. Второй параметр -
это XML DB URI (XDBUri), /public/contact_simple.xsd, обращающиеся к файлу contact_simple.xsd в папке /public репозитория XML DB. Следующие параметры определяют регистрируемую схему: локальная - (LOCAL=>TRUE) или глобальная (LOCAL=>GLOBAL), а также что будет создано: объектные типы - (GENTYPES=>TRUE) и таблицы по умолчанию (default) (GENTABLES=>TRUE). Параметр GENBEAN не обязателен и в данное время не выполняет никакой функции. Если XML схема зарегистрирована как глобальная в XML DB, то она может быть совместно используемой различными пользователями базы данных. Иначе совместное использование XML схемы не разрешается. Можно установить GENTABLES=>FALSE, если не надо, чтобы перед регистрацией XML схемы Oracle XML DB создавал default таблицы. В таком случае можно создать XMLType таблицы, используя ключевое слово XMLSCHEMA, как показано ниже:
CREATE TABLE customer_xmltype_tbl OF XMLTYPE
XMLSCHEMA "http://localhost:8080/public/contact_simple.xsd"
ELEMENT "Customer";
Кроме того, можно использовать следующий синтаксис для определения столбцов XMLType, хранящихся при использовани XML Schema:
CREATE TABLE customer_col_tbl(
id NUMBER,
record XMLType)
XMLTYPE COLUMN record STORE AS OBJECT RELATIONAL
XMLSCHEMA "http://localhost:8080/public/contact_simple.xsd"
ELEMENT "Customer";
Коль скоро для хранения XMLType столбцов и таблиц применяются одни и те же приемы, в последующих секциях мы будем детально рассматривать только XMLType таблицы на XML Schema.
В процессе регистрации XML схемы можно использовать следующую команду для создания трассировочного файла в [директории, определяемой параметром инициализации USER_DUMP_DIR], в котором отразятся DLL, используемые для создания объектных таблиц и типов данных:
ALTER SESSION SET EVENTS='31098' TRACE NAME CONTEXT FOREVER;
Для размещения трассировочного файла необходимо проверить ID идентификатор текущей сессии, обратившись к представлениям V$SESSION и V$PROCESS. Перед запросом к V$SESSION и V$PROCESS от имени пользователя DEMO, вам необходимо войти как SYS и дать пользователю DEMO привилегию SELECT из представлений V$SESSION и V$PROCESS, как показано далее:
GRANT SELECT ON V_$SESSION TO DEMO;
GRANT SELECT ON V_$PROCESS TO DEMO;
ЗАМЕЧАНИЕ
Коль скоро V$SESSION и V$PROCESS - это просто синонимы представлений, то никаких других привилегий на них дать нельзя.
Применив следующую SQL команду можно найти идентификатор сессии, которая соответствует трассировочному файлу:
SELECT a.spid
FROM V$PROCESS a, V$SESSION b
WHERE a.addr=b.paddr
AND b.audsid=userenv('sessionid');
Возвращаемое значение:
SPID
------------
2796
У трассировочного файла есть имя, структурированное как orclX_ora_<Session_id>.trc и можно узнать [значение параметра] USER_DUPM_DIR, выполнив следующую команду от лица SYS:
SQL> SHOW PARAMETERS user_dump_dest
NAME TYPE VALUE
-----------------------------------------------------------
user_dump_dest string D:\ORACLE\ADMIN\ORCLX\UDUMP
И далее, наличие трассировочного файла orclX_ora_<Session_id>.trc в USER_DUPM_DIR можно проверить следующей командой:
SQL> host ls d:\oracle\admin\orclX\udump\orclX_ora_2796.trc
orclX_ora_2796.trc
Так как этот файл содержит список DDL, используемых для создания объектных таблиц или типов данных, это нужная справка при отладке регистрации XML схемы.
Теперь давайте более подробно рассмотрим созданную структуру хранения, выполнив в SQL *Plus следующую команду:
SQL> SELECT object_name, object_type
2 FROM USER_OBJECTS
3 WHERE object_name LIKE '%Customer%';
OBJECT_NAME OBJECT_TYPE
------------------------- --------------------
Customer260_TAB TABLE
Customer260_TAB$xd TRIGGER
CustomerType259_T TYPE
Результат показывает, что в процессе регистрации XML схемы были созданы три объекта. Если более детально посмотреть на определения типов и таблиц, то можно увидить и другую информацию о созданных объектах. Во-первых, можно получить структуру таблицы Customer260_TAB:
SQL> DESC "Customer260_TAB";
В результате имеем следующее:
Name Null? Type
----------------------------------------- -------- -------------------
TABLE of SYS.XMLTYPE(XMLSchema "http://localhost:8080/public/contact_
simple.xsd" Element "
Customer") STORAGE Object-relational TYPE "CustomerType259_T"
ЗАМЕЧАНИЕ
Даже если XML элемент использует смешанный регистр или нижний регистр (mixed case or lowercase), по умолчанию имена default таблицы и объектов будут зависимы от регистра. Следовательно, необходимо использовать двойные кавычки при обращениях к таким именам, как “Customer260_TAB”.
Представленная выше структура показывает что:
- Customer260_TAB -
это XMLType таблица
- XMLType объекты в таблице ассоциированы с зарегистрированной XML схемой http://localhost:8080/public/contact_simple.xsd
- Корневой элемент XML документа - <Customer>
- Объектный тип, использованный для сохранения XMLType, - CustomerType259_T
Глядя на эту структуру CustomerType259_T, можно увидеть, что этот тип содержит
SQL> DESC "CustomerType259_T"
"CustomerType259_T" is NOT FINAL
Name Null? Type
----------------------------------- -------- ------------------------
SYS_XDBPD$ XDB.XDB$RAW_LIST_T
NAME VARCHAR2(4000 CHAR)
EMAIL VARCHAR2(4000 CHAR)
ADDRESS VARCHAR2(4000 CHAR)
PHONE VARCHAR2(4000 CHAR)
DESCRIPTION contentType257_T
Все XML элементы в XMLType корреспондированы с соответствующими типах данных базы данных. В этом примере элементы NAME, EMAIL, ADDRESS и PHONE, как простейшие типы в XML схеме, сохранены как VARCHAR2. Так как в XML схеме нет ограничения на длину строки, Oracle XML DB установил 4000 символов, как значение по умолчанию ширины данных столбцов. С другой стороны, новые объектные типы были созданы для сложных типов, определенных в XML схеме. В данном примере contentType257_T создан для хранения описания заказчиков, как показано далее:
SQL> DESC "contentType257_T";
"contentType257_T" is NOT FINAL
Name Null? Type
---------------------------------- -------- ------------------------
SYS_XDBPD$ XDB.XDB$RAW_LIST_T
SYS_XDBANY258$ VARCHAR2(4000 CHAR)
Заметим, что Oracle XML DB определяет столбец SYS_XDBANY258$ как VARCHAR2 (4000) для хранения элемента <xsd:any/>, определенного в элементе <DESCRIPTION>. Столбец SYS_XDBPD$ - это позиция столбца дескриптора, созданного XML DB для сохранить DOM точность XML документов. Информация, такая как: комментарии, инструкции обработки, префиксы пространства имен и список родственных XML элементов, сохраняется в столбце SYS_XDBPD$. Следовательно, этот столбец используется, чтобы сохранить целостность оригинального XML документа в DOM трансверсалях (transversals).
Для еще более детального изучения таблицы Customer260_TAB следует запросить представление USER_TAB_COLS:
SQL> SELECT column_name,data_type,
2 CASE WHEN hidden_column='YES' THEN 'hidden'
3 WHEN virtual_column='YES' THEN 'virtual'
4 ELSE null END as attr
5 FROM USER_TAB_COLS
6 WHERE table_name='Customer260_TAB'
7 ORDER by virtual_column desc, column_name;
COLUMN_NAME DATA_TYPE ATTR
-------------------- ------------------------- -------
SYS_NC_ROWINFO$ XMLTYPE virtual
XMLDATA CustomerType259_T hidden
ACLOID RAW hidden
OWNERID RAW hidden
SYS_NC00007$ RAW hidden
SYS_NC00014$ RAW hidden
SYS_NC_OID$ RAW hidden
SYS_NC00009$ VARCHAR2 hidden
SYS_NC00010$ VARCHAR2 hidden
SYS_NC00011$ VARCHAR2 hidden
SYS_NC00012$ VARCHAR2 hidden
SYS_NC00016$ VARCHAR2 hidden
SYS_NC00008$ XDB$RAW_LIST_T hidden
SYS_NC00015$ XDB$RAW_LIST_T hidden
XMLEXTRA XMLTYPEEXTRA hidden
SYS_NC00004$ XMLTYPEPI hidden
SYS_NC00005$ XMLTYPEPI hidden
SYS_NC00013$ contentType257_T hidden
Заметим, что выражение CASE выбирает результат из одной или более альтернатив. Оно использует опцию SELECTOR для специфицирования выражения, чье значение определяет, какую из альтернатив возвращать. Стандартное выражение CASE имеет следующую форму:
CASE selector
WHEN expression1 THEN result1
WHEN expression2 THEN result2
...
WHEN expressionN THEN resultN
[ELSE resultN+1]
END;
Из запроса можно видеть, что таблица Customer260_TAB содержит один виртуальный (virtual) столбец с именем SYS_NC_ROWINFO$, несколько скрытых (hidden) столбцов, включая XMLDATA, ACLOID, OWNERID, XMLEXTRA, и набор столбцов $SYS_NC<number>$.
Виртуальный столбец SYS_NC_ROWINFO$ - это объект XMLType, который идентифицирует строки XMLType таблицы. Например, в триггерах XMLType таблиц можно использовать :new.SYS_NC_ROWINFO$ для обращения к текущей строке данных.
Столбец XMLDATA ссылается на объекты SQL, используемые для сохранения XMLType. Это полезно, когда надо запросить или создать индексы в XMLType, полностью работая только с объектами SQL. В предшествующем примере XMLDATA - это псевдоним для объекта CustomerType259_T. Следовательно, можно добавить уникальное ограничение целостности (a unique constraint) на элемент EMAIL, ссылаясь на него, как XMLDATA.EMAIL, что показано далее:
ALTER TABLE Customer260_TAB ADD UNIQUE(XMLDATA.EMAIL);
XMLDATA.EMAIL ссылается на объекту, сохраняя контент элементов EMAIL в записях о клиентах. При наличии ограничения UNIQUE при попытке еще раз добавить такую же запись о клиенте, вы столкнетесь со следующей ошибкой:
ORA-00001: unique constraint (DEMO.SYS_C003626) violated
Некоторые из скрытых столбцов Customer260_TAB используются репозиторием Oracle XML DB. Например, в Oracle XML DB репозитории Access Control List (ACL) определяет разрешения для каждого ресурса. ACLOID специфицирует разрешения ACL для XMLType таблицы, а OWNERID специфицирует идентификатор владельца таблицы. Другие скрытые столбцы используются для построения иерархических отношений между XML элементами.
Исключение составляют XMLDATA и SYS_NC_ROWINFO$. Этими XMLType столбцами нельзя манипулировать или получить прямой доступ.
Аннотации XML схемы
Для управления соответствим между хранением XMLType и схемами XML нужно использовать аннотации Oracle XML DB. В Oracle Database 10g эти XML Schema аннотации представляют собой набор атрибутов, добавленных в XML схему, декларирующую имена объектов SQL, типы данных и разнообразные опции хранения. Все эти аннотации находятся в пространстве имен Oracle XML DB, http://xmlns.oracle.com/xdb, обычно использующим префикс xdb). Эти аннотации, главным образом, можно использовать, чтобы определить следующее:
- DefaultTable -
Имя и атрибуты хранения XMLType таблицы по умолчанию (default), сохраняющей XML документы.
- SQLNames -
SQL имена для XML элементов, определенных в XML схеме.
- SQLTypes -
Имена типов SQL данных, используемых для хранения простых или составных типов данных, описанных в XML схеме. Для неограниченного XML элемента, обращающегося к набору SQL типов, xdb:SQLCollType используется для специфицирования имени типа.
- MaintainDOM
- Атрибут, говорящий Oracle XML DB надо ли сохранять DOM точность элемента на выходе.
- Storage Options
- Аннотации XML DB, такие, как: xdb:storeVarrayAsTable, xdb:mapUnboundedStringToLob, xdb:maintainOrder и xdb:SQLInline, специфицирующие возможности оптимального хранения.
Давайте рассмотрим следующую аннотированную XML схему для записей о клиентах customer_simple_ann.xsd, испытаем некую полезную технику разработки, а затем зарегистрируем ее в XML DB.
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xdb="http://xmlns.oracle.com/xdb" xdb:storeVarrayAsTable="true">
<xsd:element name="Customer" type="CustomerType"
xdb:defaultTable="CUSTOMER"/>
<xsd:complexType name="CustomerType" xdb:maintainDOM="false">
<xsd:sequence>
<xsd:element name="NAME" type="xsd:string"
xdb:SQLName="NAME" xdb:SQLType="VARCHAR2"/>
<xsd:element name="EMAIL" type="xsd:string"
xdb:SQLName="EMAIL" xdb:SQLType="VARCHAR2"/>
<xsd:element name="ADDRESS" type="xsd:string" maxOccurs="unbounded"
xdb:SQLName="ADDRESS" xdb:SQLCollType="ADDRESS_TYPE"
xdb:SQLType="VARCHAR2" xbd:maintainOrder="false"/>
<xsd:element name="PHONE" type="phoneType"
xdb:SQLName="PHONE"/>
<xsd:element name="DESCRIPTION" type="contentType"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="contentType" mixed="true"
xdb:SQLType="CLOB" xdb:maintainDOM="true">
<xsd:sequence>
<xsd:any minOccurs="0" maxOccurs="unbounded"
processContents="skip"/>
</xsd:sequence>
</xsd:complexType>
<xsd:simpleType name="phoneType">
<xsd:restriction base="xsd:string">
<xsd:pattern value="\(\d{3}\)\d{3}-\d{4}"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
Глядя на этот пример, первая вещь, которую надо сделать при аннотировании XML схемы состоит в том, чтобы включить объявление пространства имен Oracle XML DB xmlns:xdb=”http://xmlns.oracle.com/xdb” в элемент <schema>. Префикс этого пространства имен затем используется, чтобы квалифицировать все аннотации Oracle XML DB.
Далее, xdb:storeVarrayAsTable=”true”, - это глобальная XML DB аннотация, которая говорит XML DB сохранить все элементы VARRAY во вложенных (nested) объектных таблицах. Эта аннотация способствует ускорению запросов к XML элементам, которые определены с помощью maxOccurs>1. Например, в customer_simple_ann.xsd эта аннотация влияет на сохранение элементов <ADDRESS>.
Далее, вы можете определить аннотацию XML DB xdb:mapUnboundedStringToLob=”true” в элементе <schema>, чтобы установить соответствие х строк в CLOB и безразмерных двоичных данных в BLOB при табличном хранении “вне строки” (out-of-online). По умолчанию установлено значение false. Таким образом, все безразмерные строки определены в XML схеме и отображаемы в VARCHAR2(4000), а безразмерные двоичные данные отображены в RAW(2000) при табличном хранении “в строке” (inline). Но, коль скоро inline-таблицы перестали быть эффективным средством для хранения больших XML документов, нужно устанавливать xdb:mapUnboundedStringToLob=”true”.
Для всех глобальных сложных и для простейших типов можно определить следующие аннотации XML DB, которые специфицируют соответствующие SQL имена и типы данных:
- xdb:SQLType -
Определяет SQL тип, отображающий определение типа XML схемы. Эту аннотацию следует использовать во избежание присваивания сгенерированных XML DB имен типам данных SQL.
- xdb:maintainDOM –
Определяет, должен ли сложный тип поддержать DOM точность. В нормальном режиме нужно установить аннотацию в false. Иначе, по умолчанию XML DB будет добавлять атрибут SYS_XDBPD$ (дескриптор позиции) в каждый созданный объектный тип для сохранения такой информации, как: комментарии, инструкции обработки и общие (sibling букв. - имеющие общего "родителя" – словарь Lingvo) элементы упорядоченност в XML, что, тем самым, увеличивает затраты на хранение. Например, для того, чтобы не применять DOM точность в записях о клиентах, устанавливается xdb:maintainDOM=”false” в CustomerType.
ЗАМЕЧАНИЕ
xdb:SQLName не разрешается в описаниях complexType и simpleType. Иначе, вы получите следующую ошибку:
ORA-30937: No schema definition for ‘SQLName’
(ORA_30937. Нет описания схемы для ‘SQLName’)
(пространство имен ‘http://xmlns.oracle.com/xdb’) в родительском ‘complexType’.
В корневом элементе XML документа нужно специфицировать атрибут xdb:defaultTable и опционально использовать xdb:tableProps для установки атрибутов таблицы:
- xdb:defaultTable -
Специфицирует имя таблицы, в которой может быть сохранен XML экземпляр этой схемы. Он устанавливает связь между репозиторием XML DB и этой таблицей, таким образом, любая вставка, обновление и удаление XML документа, согласующегося с этой XML схемой в этом репозитории XML DB, будет иметь соответствующее изменение в default таблице и наоборот. В примере таблица customer будет создана как default таблица.
- xdb:tableProps -
Специфицирует свойства default таблицы в синтаксисе SQL, что дописано в конец предложения CREATE TABLE.
Для всех XML элементов должно специфицировать имя и тип элемента, если их базовый тип не содержится среди глобальных типов, описанных в XML схеме, которая была аннотирована. Следующий список XML DB аннотаций для XML элементов:
- xdb:SQLName
- Специфицирует имя SQL объекта, который отображает XML элемент
- xdb:SQLType -
Специфицирует имя SQL типа, соответствующего XML элементу xdb:SQLInline – Специфицирует, требуется ли Oracle XML DB генерировать новую объектную таблицу и определять XMLType REFs для сохранения XML элементов. Настройка по умолчанию - true, то есть, REF'ы не определяются. Значение true этой аннотации затрагивает все элементы верхнего уровня, декларированные в XML схеме и XML элементу с maxOccures > 1. Для хранения в режиме “out-of-online” необходимо изменить значение на false. Это повысит производительность зп счет устранения блокировок таблиц.
- xdb:SQLCollType -
Специфицирует имя типа SQL коллекции, соответствующей XML элементу, который имеет maxOccurs > 1. Например, в элементе <ADDRESS> добавлен xdb:SQLCollType=”ADDRESS_TYPE”. По умолчанию коллекция (the collection) использует VARRAY. Поскольку установлено xdb:storeVarrayAsTable=”true”, местом хранения VARRAY является Ordered Collections in Table (OCT) в отличие от LOB (по умолчанию). Это полезно, когда желательно создать ограничения целостности на элемент.
В отличие от запоминания всех возможных аннотаций, мы делаем список наиболее используемых XML DB аннотаций. В итоге, когда аннотируются XML схемы, надо иметь в виду следующее.
Во-первых, необходимо специфицировать имя default таблицы, используя xdb:defaultTable и SQL имя для каждого XML элемента и типа данных в XML схеме, для чего используются xdb:SQLName, xdb:CollType или xdb:SQLType. Следует заметить, что в примере:
- xdb:SQLName
описывает SQL имена для XML элементов
- xdb:CollType
описывает SQL имена только для XML элементов со значением maxOccurs > 1
- xdb:SQLType
описывает SQL имена для всех complexType и simpleType, которые не используют отображение по умолчанию, предусмотренное Oracle XML DB
Определение SQL имен, используя аннотации XML схемы, полезно, потому как сгенерированные системой имена запомнить не просто. Конечно же, должно учитывать определение всех SQL имен, напечатанных прописными буквами для исключения имен с учетом регистра в базе данных, которые требуют использования двойных кавычек при обращении к объектам SQL. Например, без преобразования букв в прописные надо писать “Customer260_TAB”, а не CUSTOMER260_TAB при обращении к default таблице, хранящей записи о клиентах.
ЗАМЕЧАНИЕ
Для XML документов и типов, если не используются xdb:SQLName, xdb:CollType или xdb:SQLType, Oracle XML DB будет использовать имя элемента или типа данных для создания SQL имени. Так как XML регистро-зависим, то и SQL имя будет регистро-зависимым, требуя повсюду использования кавычек для ссылки на них. Эта аннотация также полезна, если имя XML типа или элемента длинное или есть конфликт имен в XML схеме.
Далее следует определить хранение, минимизируя любое дополнительное сохранение данных, избегая, например, хранение DOM точности. Это же надо иметь в виду при организации хранения поддеревьев и сложных типов, как CLOB’ы, когда нет нужды в XPath запросах по контенту, устанавливая xdb:SQLTypes=”CLOB”. Oracle XML DB не будет делить эти XML данные, сохраняя, таким образом, время и ресурсы.
Наконец, когда обрабатываются малые, но безразмерные XML элементы, нужно сохранять контент, как VARRAY, используя установку xdb:storeVarrayAsTable=”false”. Для больших безразмерных элементов можно использовать вложенные таблицы, в элементе <schema> специфицируя xdb:storeVarrayAsTable=”true”, или использовать вложенные таблицы, установив для лучшего выполнения на элемент xdb:maintainOrder=”false”.
Загрузка XML данных
После того, как определено хранение XMLType, можно загружать данные в XMLType таблицы, используя SQL, а именно протокол API или утилиту SQL*Loader.
Использование SQL команд
Простейший способ для загрузки XML данных в XMLType таблицы - использование команды INSERT SQL, как это показано на следующем примере:
INSERT INTO customer VALUES(XMLType('<Customer>
<NAME>Steve Joes</NAME>
<EMAIL>Steve.Joes@example.com</EMAIL>
<ADDRESS>Someroad, Somecity, Redwood Shores, CA 94065, U.S.A</ADDRESS>
<PHONE>6505723456</PHONE>
<DESCRIPTION>Very Important US Customer</DESCRIPTION>
</Customer>').CreateSchemaBasedXML(
'http://localhost:8080/public/contact_simple_ann.xsd'));
Используя этот подход, можно сконструировать XMLType экземпляр из XML в VARCHAR2, CLOB или BFILE и опционально использовать функцию XMLType.CreateSchemaBasedXML() для обращения к зарегистрированной схеме.
Не применяя функцию XMLType.CreateSchemaBasedXML(), можно вставить XML в XMLTypes, базированных на XML Schema, âêëþ÷àÿ XML Schema ссылку на корневой элемент XML документа, используя атрибуты размещения XML схемы, среди которых имеются xsi:schemaLocation и xsi:noNamespaceSchemaLocation:
INSERT INTO customer
values(XMLType('<Customer xmlns:xsi="http://www.w3.org/2001/XMLSchema
-instance" xsi:noNamespaceSchemaLocation="http://localhost:8080/public/
contact_simple_ann.xsd">
<NAME>Steve Joes</NAME>
<EMAIL>Steve.Joes@example.com</EMAIL>
<ADDRESS>Someroad, Somecity, Redwood Shores, CA 94065, U.S.A</ADDRESS>
<PHONE>6505723456</PHONE>
<DESCRIPTION>Very Important US Customer</DESCRIPTION>
</Customer>'));
Атрибут xmlns:xsi=”http://www.w3.org/20041/XMLSchema-instance” объявляет пространство имен для экземпляра XML Schema. Атрибут xsi:noNamespaceSchemaLocation=
”http://localhost:8080/public/contact_simple_ann.xsd” специфицирует URL зарегистрированной XML схемы. В этом примере, если XML документы не обладает пространством имен, используется xsi:noNamespaceSchemaLocation. Если XML документ содержит пространство имен, например, XML схема для XML документа определяет целевое пространство имен как targetNamespace=”http://www.example.com/customer”, тогда необходимо использовать атрибут xsi:schemaLocation, как показано ниже:
xsi:schemaLocation= "http://www.example.com/customer
http://localhost:8080/
public/contact_simple_ann.xsd"
Атрибут содержит targetNamespace, http://example.com/customer и URL XML схемы http://localhost:8080/public/contact_simple_ann.xsd.
Использование интерфейсов репозитория Oracle XML DB
Репозиторий XML DB поддерживает протоколы взаимодействия, включая FTP и WebDAV/HTTP, используемых для вставки XML и других типов документов. Как уже говорилось в Главе 8, вы можете создать папку WebDAV и использовать ее для копирования или редактирования XML файлов в репозитории XML DB, как если бы это была еще одна директория на вашем диске. Когда используются протоколы взаимодействия, XML документ должен иметь атрибуты расположения XML схемы для гарантии того, что данные вставятся в default таблицы, созданные при регистрации XML схемы. В следующем примере используется FTP интерфейс для вставки записей о клиентах в default таблицу customer после регистрации contact_simple_ann.xsd в XML DB:
D:\>ftp
ftp> open localhost 2100
Connected to [Machine_Name] 220 [Machine_Name].FTP Server (Oracle XML
DB/Oracle Database 10g Enterprise Edition Release X.X.X.X.X) ready.
User ([Machine_Name]:(none)): demo
331 pass required for DEMO
Password:
230 DEMO logged in
ftp> cd public
250 CWD Command successful
ftp> put customer1.xml
200 PORT Command successful
150 ASCII Data Connection
226 ASCII Transfer Complete
ftp: 444 bytes sent in 0.00Seconds 444000.00Kbytes/sec.
ftp> ls customer1.xml
200 PORT Command successful
150 ASCII Data Connection
customer1.xml
226 ASCII Transfer Complete
ftp: 15 bytes received in 0.00Seconds 15000.00Kbytes/sec.
ftp>bye
После этих операций новая запись о клиенте вставляется как в репозиторий XML DB в директорию /public, так и в default таблицу customer. В дополнение к двум записям, вставленным с помощью SQL, теперь существует третья запись в таблице customer:
SQL> SELECT count(1) FROM customer;
COUNT(1)
----------
3
Мы обсудим возможности репозитория XML DB в секции “Репозиторий Oracle XML DB”. А сейчас пока требуется знать только, что не важно, какая директория в репозитории XML DB используется для хранения XML документа, новая запись о клиенте будет всегда вставляться в default XMLType таблицу на такой срок, который потребуется для отправки по соответствующему URL зарегистрированной XML схемы.
Использование SQL*Loader
SQL*Loader был широко распространенным инструментом для загрузки данных в базу данных Oracle. В Oracle Database 10g SQL*Loader помогает загружать XML данные в XMLType столбцы или XMLType таблицы, независимо от лежащей в основе памяти хранения. Другими словами, можно использовать один и тот же метод для загрузки XML данных в CLOB или в объектно-реляционный XMLType. Кроме того, SQL*Loader позволяет загрузку XML данных, используя оба метода: традиционный и прямой загрузки. Традиционный путь - это метод по умолчанию, который использует SQL для загрузки данных в базу данных Oracle. Прямой путь обходит SQL и погружает данные непосредственно в файлы базы данных Oracle.
Для загрузки XML данных, используя SQL*Loader, необходимо применять управляющий файл, описывающий входные данные и целевую таблицу и столбцы таблицы. Например, для вставки двух записей о клиентах: customer3.xml и customer4.xml, в таблицу customer, следует создать управляющий файл, как показано далее:
LOAD DATA
INFILE *
INTO TABLE customer
APPEND
XMLType(XMLDATA)(
lobfn FILLER CHAR TERMINATED BY ',',
XMLDATA LOBFILE(lobfn) TERMINATED BY EOF
)
BEGINDATA
xml/customer3.xml,
xml/customer4.xml
Управляющий файл сообщает SQL*Loader, что загружаемые данные (LOAD DATA) содержатся в управляющем файле (INFILE*) добавляются в конец (APPEND) таблицы customer (INTO TABLE customer). XMLType (XMLDATA) ссылается на новые данные как XMLType. До тех пор пока эта операция является дописывающей (appending), SQL*Loader будет загружать новые данные без перезаписывания старых записей о клиентах. Если же вместо этого использовать REPLACE, то старые записи будут удалены перед вставкой новых данных.
Оператор lobfn - это поле FILLER. В SQL*Loader поля FILLER используются для собирания данных из входых строк. Другими словами, поля FILLER не относятся ни к одному столбцу таблицы; вместо этого они используются для пропуска или выбора данных из входного потока. В данном примере lobfn используется для получения имен XML документов после BEGIN DATA, имена разграничиваются запятыми (TERMINATED BY ‘,’). Актуальные XML данные в файлах разделяются символом “конец файла” [end-of-file] (EOF).
После того как управляющий файл будет создан, следует дополнить [переменную] среды PATH директорией $ORACLE_HOME\bin, а затем запустить выполнить команду, чтобы запустить sqlldr – утилиту командной строки SQL*Loader:
D:\>sqlldr userid=demo/demo control=customerLoad.ctl
SQL*Loader: Release X on Thu Jun 26 22:26:53 2003
(c) Copyright 2001 Oracle Corporation. All rights reserved.
Commit point reached - logical record count 2
Userid определяет имя и пароль для пользователя базы данных, которому принадлежит таблица customer. Опция control определяет имя управляющего файла. Результат показывает, что две логических записи были распознаны SQL*Loader. Последующая информация о [выполнении] sqlldr может быть найдена в файле <control_file_name>.log. Можно определить direct=y, если требуется использовать прямой способ загрузки XML данных. В сравнении с традиционным, прямой способ быстрее, так как он обходит SQL уровень и продвигает XML данные в файлы базы данных Oracle без запуска дополнительных процедур или принудительной проверки.
Проверка достоверности XML схемы
В процессе загрузки XML или после обновления контента в XMLTypes, базирующихся на XML Schema, Oracle XML DB просто проверяет, правильно расширяется XML документ с проверками объектов, вместо выполнения проверки достоверности всей XML Schema. Другими словами, Oracle XML DB выполняет только ограниченные проверки для того, чтобы удостовериться, что XML документ согласуется с объектно-реляционным хранением. Например, XML DB проверит, существал ли элемент <PHONE> до вставки записей о клиентах. Это не остановит вставку данных, если номера телефонов нарушают шаблон строки, определенный в XML схеме.
Для очистки от неправильных данных, которые могут быть вставлены в XMLTypes, необходимо явно запрашивать проверку достоверности XML Schema. Простейший способ это сделать - до выполнения операций INSERT создать TRIGGER, как показано ниже:
CREATE OR REPLACE TRIGGER customer_insert
AFTER INSERT ON customer
FOR EACH ROW
DECLARE
doc XMLType;
BEGIN
doc := :new.SYS_NC_ROWINFO$;
XMLType.schemaValidate(doc);
END;
Если только триггер задействован, проводится полная проверка достоверности всякий раз, когда вставляются данные в таблицу customer:
INSERT INTO customer VALUES(
XMLType('<CUSTOMER xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://localhost:8080/public/
contact_simple_ann.xsd">
<NAME>Steve Joes</NAME>
<EMAIL>Steve.Joes@example.com</EMAIL>
<ADDRESS>Someroad, Somecity, Redwood Shores, CA 94065, U.S.A</ADDRESS>
<PHONE>6505723456</PHONE>
<DESCRIPTION>Very Important US Customer</DESCRIPTION>
</CUSTOMER>'));
Таким образом, этот пример вернет следующие ошибки:
INSERT INTO customer
*
ERROR at line 1:
ORA-31154: invalid XML document
ORA-19202: Error occurred in XML processing
LSX-00333: literal "6505723456" is not valid with respect to the pattern
ORA-06512: at "SYS.XMLTYPE", line 333
ORA-06512: at "DEMO.CUSTOMER_INSERT", line 5
ORA-04088: error during execution of trigger 'DEMO.CUSTOMER_INSERT'
Как можно видеть, сообщение об ошибке утверждает, что номер телефона не следует шаблону строки, определенному в XML схеме. После того, как вы обновили номер телефона, можно попробовать снова:
SQL> INSERT INTO customer VALUES(
XMLType('<Customer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://localhost:8080/public/
contact_simple_ann.xsd">
<NAME>Steve Joes</NAME>
<EMAIL>Steve.Joes@example.com</EMAIL>
<ADDRESS>Someroad, Somecity, Redwood Shores, CA 94065, U.S.A
</ADDRESS>
<PHONE>(650)572-3456</PHONE>
<DESCRIPTION>Very Important US Customer</DESCRIPTION>
</CUSTOMER>'));
Добавлена новая правильная запись о клиенте. Следует проверить статус проверки достоверности XML Schema äëÿ объекта XMLType, используя функцию XMLType.isSchemaValid() или функцию XMLType.isSchemaValidated():
SQL> SELECT x.isSchemaValid() FROM customer x;
X.ISSCHEMAVALID()
-----------------
1
0
...0
Предыдущий результат показывает, что есть только одна запись в таблице и она правильная по XML схеме. Записи, вставленные до этого, не имели статуса valid (правильная). Это так потому, что функция XMLType.schemaValidate() проверяет на достоверность объект XMLType и обновляет статус достоверности объектов XMLType в XML DB.
ЗАМЕЧАНИЕ
Включив полную проверку достоверности получим значительный негативный эффект при выполнении INSERT, таким образом, это следует использовать только в случае необходимости. Обычно лучше проводить проверку достоверности во время создания документа или на среднем уровне(middle tier).
Часть 2