![]() |
Хранение XML данных. Часть 1Источник: citforum Марк Скандина, Бен Чанг, Джайню Ванг
В Oracle Database 10 g у вас есть несколько возможностей хранения XML данных. Вы можете разделить XML документ на части и хранить данные в одной или нескольких реляционных таблицах, помещать XMLType-ы целиком в CLOB-ы или зарегистрировать XML схему и хранить их в объектно-ориентированой памяти на языке XML Schema, предназначеном для XMLType. Если нет необходимости корректировки XML-контента, также можно сохранить XML документы как внешние, используя механизм External Tables (внешних таблиц). Эта глава содержит обзор способов хранения XML, доступных в Oracle Database 10 g и демонстрирует различные варианты применения этих технологий. Даются примеры использования утилит Oracle SQL*Loader и XML SQL Utility (XSU) для загрузки XML документов в или XMLType-таблицу, или реляционную таблицу в Oracle Database 10 g. Мы начнем с простейшего формата сохранения: 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". Представленная выше структура показывает что:
Глядя на эту структуру 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 10 g эти XML Schema аннотации представляют собой набор атрибутов, добавленных в XML схему, декларирующую имена объектов SQL, типы данных и разнообразные опции хранения. Все эти аннотации находятся в пространстве имен Oracle XML DB, http://xmlns.oracle.com/xdb, обычно использующим префикс xdb). Эти аннотации, главным образом, можно использовать, чтобы определить следующее:
Давайте рассмотрим следующую аннотированную 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:SQLName не разрешается в описаниях complexType и simpleType. Иначе, вы получите следующую ошибку: ORA-30937: No schema definition for ‘SQLName’ (ORA_30937. Нет описания схемы для ‘SQLName’) (пространство имен ‘http://xmlns.oracle.com/xdb’) в родительском ‘complexType’. В корневом элементе XML документа нужно специфицировать атрибут xdb:defaultTable и опционально использовать xdb:tableProps для установки атрибутов таблицы:
Для всех XML элементов должно специфицировать имя и тип элемента, если их базовый тип не содержится среди глобальных типов, описанных в XML схеме, которая была аннотирована. Следующий список XML DB аннотаций для XML элементов:
В отличие от запоминания всех возможных аннотаций, мы делаем список наиболее используемых XML DB аннотаций. В итоге, когда аннотируются XML схемы, надо иметь в виду следующее. Во-первых, необходимо специфицировать имя default таблицы, используя xdb:defaultTable и SQL имя для каждого XML элемента и типа данных в XML схеме, для чего используются xdb:SQLName, xdb:CollType или xdb:SQLType. Следует заметить, что в примере:
Определение 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= 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*LoaderSQL*Loader был широко распространенным инструментом для загрузки данных в базу данных Oracle. В Oracle Database 10 g 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). Глава 9 из книги "Oracle Database 10g XML & SQL: Design, Build, & Manage XML Applications in Java, C, C++, & PL/SQL" by Mark Scardina, Ben Chang, Jinyu Wang, изд. Osborne, ISBN: 0072229527, 2004, 600 стр. Оригинальный текст главы 9 выложен в открытом доступе по адресу http://www.oracle.com/technology/books/pdfs/ch9_oracle10g_xml.pdf Перевод: Oracle Magazine RE |