Часть 1
Часть 2
Репозиторий Oracle XML DB
Репозиторий Oracle XML DB может функционировать как файловая система в базе данных Oracle. Любые данные репозитория Oracle XML DB отображаются на ресурсы, которые имеют путевое (pathname – составное) имя (или URL) и сохранены в BLOB или в объекте XMLType. Репозиторий XML DB предоставляет возможность исчерпывающего управления этими ресурсами.
Вы уже изучили, как загружать XML с помощью протокола интерфейсов репозитория XML DB. В этой секции мы обсудим другие темы: возможность версии контролировать документы и созданные связи, управление ресурсами. Мы также обсудим основные PL/SQL пакеты, обеспечивающие эту функциональность:
- DBMS_XDB
обеспечивает функции управления ресурсами и сессиями репозитория XML DB. Так же обеспечивается функциональность перестроения иерархических индексов.
- DBMS_XDB_VERSION
предоставляет функции для контроля версий ресурсов
Управление ресурсами
В Oracle Database 10g вы можете использовать модуль DBMS_XDB для создания и удаления ресурсов, папок-фолдеров и связей ресурсов. Вы также можете использовать этот модуль для блокирования/разблокирования ресурсов во время чтения или обновления XML данных:
DECLARE
res BOOLEAN;
xr REF XMLType;
x XMLType;
BEGIN
FOR po_rec IN (SELECT rownum id, ref(p) xref FROM customer p
ORDER BY rowid)
LOOP
res:=DBMS_XDB.createResource('/public/customer'||po_rec.id||
'.xml', po_rec.xref);
END LOOP;
END;
В этом примере все записи о клиентах считываются из таблицы customer и ресурсные XML документы, созданные в директории /public репозитория XML DB, используют функцию DBMS_XDB.createResource(). Дополнительно в репозитории XML DB можно создать папку /public/important_customer, как показано ниже:
DECLARE
retb BOOLEAN;
BEGIN
retb := DBMS_XDB.createFolder('/public/important_customer');
COMMIT;
END;
/
Далее, можно создать некий ресурс README.txt для отображения содержимого этой папки:
DECLARE
res BOOLEAN;
BEGIN
res :=
DBMS_XDB.createResource('/public/important_customer/README.txt',
'This folder lists all of the US customer who are important to
our business');
COMMIT;
END;
/
С того момента как создан в директории /public список клиентов, можно создать набор связей, вместо создания второй копии данных:
EXEC DBMS_XDB.link('/public/customer1.xml',
'/public/important_customer/','SteveJones.xml');
Если вы хотите удалить ресурс, можно использовать функцию DBMS_XDB.DeleteResource():
DBMS_XDB.DeleteResource
('/public/important_customer/SteveJones.xml');
DBMS_XDB.DeleteResource ('/public/customer1.xml');
Вы можете удалить ресурс с ресурсными на него связями. Разумеется, после перемещения оригинального ресурса все связанные ресурсы более с ним не связаны. Каждый из них вместо этого будет содержать копию данных.
Контроль версий
Пакеты DBMS_XDB_VERSION и DBMS_XDBPL/SQL обеспечивают функцию контроля версий Oracle XML DB, которая дает способ создания и управления различными версиями Version-Control Resource (VCR) в Oracle XML DB.
Когда XML DB ресурс встроен в VCR, некий флажок маркирует его как VCR, и текущий ресурс становится исходной версией. Эта версия физически не сохраняется в базе данных. Другими словами, нет дополнительной копии этого ресурса, сохраненной, когда он был сделан версией. Следующие версии сохраняются в тех же таблицах. Коль скоро версия ресурса становится системно-сгенерированной, она лишается составного (pathname) имени. Но вы все еще можете получить доступ к ресурсу через функцию, предоставленную в пакете DBMS_XDB_VERSION.
Когда проверяется ресурс, ни какой другой пользователь не может его обновить. Когда ресурс обновляется впервые, создается его копия. Вы можете сделать несколько изменений ресурса без обратного эффекта. Вы всегда будете получать последние версии ресурса, даже если у вас есть различные пользователи. Когда ресурс перезапускается, оригинальная версия, которая заканчивает работу, помещается на место обычного постоянного хранения.
Характеристики версий для VCR содержатся в репозитории XML DB. В этом релизе версионность работает только для небазируемых на схемах (non-schema-based) ресурсах. Таким образом, XMLType, базируемые на раздельных XML-документах, и XMLType CLOB, которые обладают присоединенными схемами, официально не поддерживают использование VCR. Тем не менее, мы обнаружили, что до тех пор, пока вы не создадите уникальные метаданные, ассоциированные с конкретной версией, например индексы, VCR будут работать.
ЗАМЕЧАНИЕ
Вы не можете переключиться с VCR на не-VCR.
Oracle XML DB предоставляет функции для отслеживания всех изменений в VCR Oracle XML DB. Следующий код демонстрирует эти функции:
DECLARE
resid DBMS_XDB_VERSION.RESID_TYPE;
BEGIN
resid := DBMS_XDB_VERSION.MakeVersioned('/public/important_customer/
SteveJones.xml');
END;
/
Вы можете получить идентификатор ресурса VCR:
SET AUTOPRINT ON
VAR OUT CLOB
DECLARE
resid DBMS_XDB_VERSION.RESID_TYPE;
res XMLType;
BEGIN
resid := DBMS_XDB_VERSION.MakeVersioned
('/public/important_customer/SteveJones.xml');
-- Obtain the resource
res := DBMS_XDB_VERSION.GetResourceByResId(resid);
SELECT res.getClobVal() INTO :OUT FROM dual;
END;
Для обновления VCR вам понадобится проверить ресурс, выполнить обновление файлов и затем вернуть их в репозиторий XML DB:
DECLARE
resid DBMS_XDB_VERSION.RESID_TYPE;
BEGIN
DBMS_XDB_VERSION.CheckOut('/public/important_customer/SteveJones.xml');
resid :=
DBMS_XDB_VERSION.CheckIn('/public/important_customer/SteveJones.xml');
END;
Заметим, что ресурсы не обновятся до тех пор, пока проверяется новый файл. Если вы хотите завершить проверку, вы можете “распроверить” ресурс:
DECLARE
resid DBMS_XDB_VERSION.RESID_TYPE;
BEGIN
resid :=
DBMS_XDB_VERSION.UncheckOut
('/public/important_customer/SteveJones.xml ');
END;
Сохранение XML документов в реляционных таблицах
Реляционные таблицы обычно проектируются, не принимая во внимание хранение XML. Однако во многих случаях эти таблицы могут быть использованы для сохранения расщепленных (shredded) XML-документов и порождения полезных XML-отображений с помощью создания XMLType-представлений, использующих XML-опции Oracle Database 10g, или генерирующих XML с использованием Oracle XDK.
Хранение XML-данных в реляционных таблицах удобно, если вашему приложению нужно избавиться от таких ограничений XMLType-хранения, как ограничение на эволюцию XML-схемы или реплицирование данных. Реляционное хранение также широко используется приложениями, которые нуждаются в низко уровневом доступе к данным из XML- документов, пока не требуется защита полной иерархической структуры XML.
Oracle Database 10g предоставляет обширную поддержку для загрузки, экспортирования и обработки XML-данных в реляционных таблицах. Для загрузки XML-данных вы можете использовать утилиту XML SQL Utility (XSU), которая обеспечивает оба: Java и PL/SQL программных интерфейса, а также утилиты командной строки. Утилита TransX Utility (Translation XML), построенная на XSU, упрощает дальнейшее преобразование набора символов (character set) перед загрузкой данных, а XSQL Servlet предоставляет HTTP-интерфейсы. Если для вашего приложения недостаточно функциональности, предлагаемой данными утилитами, вы можете использовать их программный API в объединении с другими библиотеками XDK для построения собственного решения.
Утилита XML SQL Utility
XSU предлагает API, базируемые на Java, утилиты командной строки и PL/SQ-пакеты, которые поддерживают загрузку XML-данных в реляционные таблицы, включая таблицы, содержащие столбцы XMLType. Мы в следующих разделах рассмотрим, как можно использовать эту функциональность.
Каноническое отображение
Первое, что вам следует сделать перед использованием XSU, это понять, будет ли использоваться каноническое отображение XSU для отображения XML в реляционные таблицы и визуализировать результаты SQL-запросов в XML. В данном каноническом отображении элемент <ROWSET> является корневым элементом XML-документа, а его дочерние элементы <ROW> отображаются в столбцы данных в таблицах. Имена дочерних элементов для каждого элемента <ROW> отображаются в имена табличных столбцов или имена объектов, из которых возвращаются результаты. Атрибуты num элементов <ROW> являются номерами, по которым доступна заказанная информация. Далее следует пример отображения XML-схемы этой структуры метаданных:
><xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="ROWSET">
<xs:complexType>
<xs:sequence>
<xs:element name="ROW">
<xs:complexType>
<xs:sequence>
<xs:any/>
</xs:sequence>
<xs:attribute name="num" type="xs:string" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
XSU предоставляет способы изменения имен элементов <ROWSET> и <ROW>. Например, таблица CUSTOMER_TBL определятся так:
CREATE TABLE CUSTOMER_TBL (
NAME VARCHAR2(100),
ADDRESS VARCHAR2(200),
EMAIL VARCHAR2(200),
PHONE VARCHAR2(50),
DESCRIPTION VARCHAR2(4000));
XML-документ отображается в таблицу каноническим отображением, как показано далее:
<ROWSET>
<ROW>
<NAME>Steve Jones</NAME>
<EMAIL>Steve.Jones@example.com</EMAIL>
<ADDRESS>Someroad, Somecity, Redwood Shores, CA 94065, U.S.A</ADDRESS>
<PHONE>6505723456</PHONE>
<DESCRIPTION>Very Important US Customer</DESCRIPTION>
</ROW>
</ROWSET>
ЗАМЕЧАНИЕ
По умолчанию все имена таблиц, столбцов и объектов пишутся на верхнем регистре. Таким образом, если вы хотите правильно вставить XML-документ со смешанными регистрами, то вам необходимо специфицировать опции ignoreCase во время использования XSU.
Чтобы надлежащим образом запустить XSU утилиту из командной строки, вам нужно установить следующие Java-пакеты в ваш Java CLASSPATH:
- xmlparserv2.jar
Oracle XML Parser для Java
- classes12.jar
Oracle JDBC драйверы
- xsu12.jar
Oracle XML SQL Utility
ЗАМЕЧАНИЕ
Вам может понадобиться вставить пакет orai18n.jar в ваш Java CLASSPATH, когда оперируете XML с различными наборами символов. Иначе вы можете получить oracle.xml.sql.OracleXMLSQLException: ‘java.sql.SQLException: Non supported character set…’
XSU зависит от синтаксического анализатора XML, чтобы построить DOM, а также зависит от JDBC-драйвера для подключения к базе данных Oracle и извлечения мета данных. После того как Java CLASSPATH установлен должным образом, вы можете запустить утилиту командной строки XSU с помощью java OracleXML, которая имеет две опции: getXML для запросов к базе данных и putXML для добавления данных в базу данных.
ЗАМЕЧАНИЕ
Операции обновления и удаления не включены в утилиту командной строки XSU, но они поддерживаются Java и API PL/SQL.
Например, для добавления XML-данных в contact01.xml можно задействовать следующую команду:
java OracleXML putXML -conn "jdbc:oracle:thin:@localhost:1521:orclX"
-user "demo/demo" -fileName "customer1_xsu.xml" "customr_tbl"
Данные добавлены в таблицу CUSTOMER_TBL в схеме demo. Для запроса содержимого таблицы и возвращения результатов в XML можно задействовать следующую XSU команду:
java OracleXML getXML -conn "jdbc:oracle:thin:@localhost:1521:orclX"
-user "demo/demo" "SELECT * FROM customer_tbl"
Возвращается следующий XML-документ:
<?xml version = '1.0'?>
<ROWSET>
<ROW num="1">
<NAME>Steve Jones</NAME>
<ADDRESS>Someroad, Somecity, Redwood Shores, CA 94065, U.S.A</ADDRESS>
<EMAIL>Steve.Jones@example.com</EMAIL>
<PHONE>6505723456</PHONE>
<DESCRIPTION>Very Important US Customer</DESCRIPTION>
</ROW>
</ROWSET>
В этом случае данные XML-документа успешно загружены в база данных. Однако добавляемые XML-документы не всегда находятся в каноническом формате. Как следует обращаться с такими документами? Обычный прием - это использование XSLT-таблицы стилей для трансформирования XML-документа в канонический формат. С другой стороны, вы можете создать объектные представления в базе данных, отображающих входной XML-формат.
Объектные представления
Если XML-документ не находится в каноническом формате, вы можете создать объектные представления или XMLType-представления, чтобы позволить XSU отображать XML-документы в таблицы базы данных. Как показано далее, контактная информация сохраняется в следующем contact.xml XML-документе:
<Contact_List>
<Contact>
<User_id>userid</User_id>
<First_Name>Steve</First_Name>
<Last_Name>Jones</Last_Name>
<Business>
<Email>Steve.Jones@oracle.com</Email>
<Phone>(650)5769801</Phone>
<Address>
<Street1>4op11</Street1>
<Street2>500 Oracle Parkway</Street2>
<City>Redwood Shores</City>
<State>CA</State>
<Zipcode>94065</Zipcode>
<Country>USA</Country>
</Address>
</Business>
</Contact>
</Contact_List>
Схема базы данных определяется, как показано далее:
CREATE TYPE address_typ AS OBJECT(
street1 VARCHAR2(200),
street2 VARCHAR2(200),
city VARCHAR2(100),
state VARCHAR2(20),
zipcode VARCHAR2(20),
country VARCHAR2(20));
/
CREATE TABLE contact_tbl(
contactid VARCHAR2(15) PRIMARY KEY,
firstname VARCHAR2(100),
lastname VARCHAR2(200),
midname VARCHAR2(50),
business_phone VARCHAR2(20),
home_phone VARCHAR2(10),
cell_phone VARCHAR2(20),
business_addr address_typ,
business_email VARCHAR2(150));
Используя каноническое отображение, XML-документ не может напрямую отобразится в столбцах таблицы, как документ, содержащий несколько уровней. Таким образом, для того, чтобы вставить XML-документ, нужно создать следующее объектное представление:
CREATE TYPE contactinfo_type AS OBJECT(
phone VARCHAR2(20),
email VARCHAR2(150),
address address_typ);
/
-- Create Object View
CREATE VIEW contact_view AS
SELECT contactid AS user_id, firstname AS first_name, lastname AS
last_name,midname AS mid_name,
contactinfo_type(business_phone,business_email,
business_addr) AS business
FROM contact_tbl;
Далее вы можете запустить следующую команду для загрузки XML-файла в CUSTOMER_VIEW:
java OracleXML putXML -conn "jdbc:oracle:thin:@localhost:1521:orclX"
-user "demo/demo" -fileName "contacts.xml" "contact_view"
В данном примере contact_view используется база данных Oracle для отображения XML- данных в базовые таблицы. Однако, во многих случаях эти типы представлений не будут обновляемыми, когда они содержат многоуровневые таблицы соединения или объекты типа наследования. Далее для обращения с совокупностью данных в этих таблицах и объектов вы должны создать INSTEAD-OF-TRIGGERS для представлений.
Деление XML-документов на фрагменты
Когда сохраняете XML-документ, вы иногда не хотите отображать каждый XML-элемент в столбцах реляционной таблицы. Вместо этого, вы можете захотеть сохранить некоторые XML-фрагменты в XML CLOB или XMLType. Следующий пример иллюстрирует подход в использование XSLT для создания таких XML-фрагментов и вставки этих же XML-фрагментов в один столбец XMLType-таблицы, используя XSU. В примере добавляемый XML-документ представлен как:
<Contact_List>
<Contact>
<User_id>jwang</User_id>
<First_Name>Jinyu</First_Name>
<Last_Name>Wang</Last_Name>
<Title>Senior Product Manager</Title>
<Description>Jinyu manages the <PRODUCT>Oracle XML Developer's
Kit</PRODUCT> product.</Description>
</Contact>
</Contact_List>
Элемент <Description> содержит смешанный контент, который мы не хотим отображать (to map) в несколько столбцов таблицы. Таблицы contact_tbl определяется, как показано далее:
CREATE TABLE contact_tbl(
contactid VARCHAR2(15) PRIMARY KEY,
firstname VARCHAR2(100),
lastname VARCHAR2(200),
midname VARCHAR2(50),
description CLOB);
Для отображения элемента <Description> в столбец description, используя XSU, вам нужно задействовать следующую setCDATA.xsl таблицу стилей XSL:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output cdata-section-elements="CODE"/>
<!-- Identity transformation -->
<xsl:template match="*|@*|comment()|processing-instruction()|
text()">
<xsl:copy>
<xsl:apply-templates select="*|@*|comment()|processing-instruction()|
text()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Description">
<xsl:element name="Description">
<xsl:copy-of select="@*|comment()|processing-instruction()"/>
<xsl:text disable-output-escaping="yes"><![CDATA[</xsl:text>
<xsl:apply-templates select="*|./*/@*|./*/comment()|./*/
processing-instruction()|text()"/>
<xsl:text disable-output-escaping="yes">]]></xsl:text>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Это XSLT-преобразование трансформирует входящий XML-документ и включит все дочерние элементы <Description> в одну секций CDATA, так что каждая секция CDATA может быть сохранена с помощью XSU в столбце description.
Вы можете модифицировать таблицу стилей XSL для вашего приложения, специфицируя различные match-атрибуты по следующему шаблону:
<xsl:template match="Description">… </ xsl:template>
XPath в match-атрибуте специфицирует корневой элемент для сохранения XML-фрагмента.
ЗАМЕЧАНИЕ
Так как XSLT требует, чтобы DOM был встроен в память, вам может потребоваться перед преобразованием разбиение большого документа.
Утилита TransX Utility
Когда происходит заполнение базы данных Oracle многоязычными данными или преобразование данных, или когда происходит кодирование, требуется проверка достоверности каждого XML-файла. Традиционный путь решения - это переключение установки NLS_LANG, как будто вы переключаетесь на загрузку файлов с различными кодовыми таблицами. Параметр NLS_LANG определяет таблицу символов для загруженного в базу данных файла. Этот подход подвержен ошибкам, потому что кодовая информация поддерживается отдельно от самих данных. Постоянно переустанавливать NLS_LANG - очень скучная работа.
При использовании TransX Utility, предусмотренной XDK, кодовая информация содержится вместе с данными в XML-документе в предопределенном формате. Таким образом, многоязыковые данные могут быть перемешены без переключения настройки NLS_LANG. TransX Utility поддерживает корректный набор символов на всем протяжении процесса транслирования данных и успешно загружает его в базу данных. Мы не будем детально рассматривать использование TransX Utility. Но мы рассмотрим некоторые примеры, чтобы вы смогли увидеть ее функциональные возможности.
Пакет DBMS_XMLSTORE
DBMS_XMLSTORE - это PL/SQL-пакет, который обеспечивает добавление XML-данных в таблицы базы данных. Эта C-базированная реализация обеспечивает лучшую производительность и системную управляемость, чем Java-базированный пакет DBMS_XMLSave. Этот пакет устраняет накладные издержки в начале работы Oracle JVM такие, как транслирование имен Java-классов при каждом вызове методов. Кроме того,
DBMS_XMLSTORE построен на основании анализатора SAX, а не на анализаторе DOM. Соответственно, он лучше масштабирует большие XML-документы. Вы можете заметить это в следующем сопоставлении, используя эталонную схему SH:
SQL> SELECT count(1) FROM sales;
COUNT(1)
----------
1136945
SQL> CREATE TABLE test AS SELECT * FROM sales;
Table created.
SQL> CREATE TABLE result AS SELECT * FROM sales WHERE 0=1;
Table created.
SQL> SELECT count(1) FROM test;
COUNT(1)
----------
1136945
SQL> SELECT count(1) FROM result;
COUNT(1)
----------
0
SQL> SET timing ON
SQL> DECLARE
2 qryCtx DBMS_XMLQuery.ctxHandle;
3 v_clob CLOB;
4 savCtx DBMS_XMLSave.ctxType;
5 v_rows NUMBER;
6 BEGIN
7 -- Query out the content
8 qryCtx := DBMS_XMLQuery.newContext('SELECT * FROM test');
9 v_clob := DBMS_XMLQuery.getXml(qryCtx);
10 DBMS_OUTPUT.PUT_LINE('CLOB size = '||DBMS_LOB.GETLENGTH(v_clob));
11 -- Save the content
12 savCtx := DBMS_XMLSave.newContext('RESULT');
13 v_rows := DBMS_XMLSave.insertxml(savCtx,v_clob);
14 DBMS_XMLSave.closeContext(savCtx);
15 DBMS_OUTPUT.PUT_LINE(v_rows || ' rows inserted...');
16 END;
17 /
DECLARE
*
ERROR at line 1:
ORA-29532: Java call terminated by uncaught Java exception:
java.lang.OutOfMemoryError
ORA-06512: at "SYS.DBMS_XMLSAVE", line 114
ORA-06512: at line 13
Elapsed: 00:11:57.05
В предшествующем примере таблица sales эталонной схемы SH, описанная в Главе 8, используется для формирования большого XML-документа, который, когда анализируется, слишком велик для сконфигурированной памяти хранения Oracle JVM. Вы можете увеличить JAVA_POOL_SIZE, чтобы выделить больше памяти для обработки, однако, это может быть не достаточно, особенно, когда эта память выбирается из пула оперативной памяти базы данных. В Oracle Database 10g вы можете воспользоваться пакетом DBMS_XMLSTORE для разрешения этой проблемы, как показано далее:
DECLARE
v_clob CLOB;
savCtx DBMS_XMLSTORE.ctxType;
v_rows NUMBER;
BEGIN
-- Query out the content
SELECT doc INTO v_clob FROM temp_clob;
-- Save the content
savCtx := DBMS_XMLSTORE.newContext('RESULT');
-- Set the update columns to improve performance
DBMS_XMLSTORE.SetUpdateColumn (savCtx, 'PROD_ID');
DBMS_XMLSTORE.SetUpdateColumn (savCtx, 'CUST_ID');
DBMS_XMLSTORE.SetUpdateColumn (savCtx, 'TIME_ID');
DBMS_XMLSTORE.SetUpdateColumn (savCtx, 'CHANNEL_ID');
DBMS_XMLSTORE.SetUpdateColumn (savCtx, 'PROMO_ID');
DBMS_XMLSTORE.SetUpdateColumn (savCtx, 'QUANTITY_SOLD');
DBMS_XMLSTORE.SetUpdateColumn (savCtx, 'AMOUNT_SOLD');
-- Insert the document
v_rows := DBMS_XMLSTORE.insertxml(savCtx,v_clob);
DBMS_XMLSTORE.closeContext(savCtx);
DBMS_OUTPUT.PUT_LINE(v_rows || ' rows inserted...');
END;
Рекомендуется использовать функцию SetUpdateColoumn() из DBMS_XMLSTORE всегда, когда это подходит, как было в предыдущем примере, потому как это позволяет программе DBMS_XMLSTORE узнать список столбцов, которые должны быть обновлены для использования явного SQL-связывания с XML-данными. Предыдущий пример использует следующее SQL-выражение при подготовке к добавлению данных:
INSERT INTO sales(prod_id, cust_id, ..., amount_sold) values
(:1, :2, ..., :6);
Это ускоряет процесс вставки данных, устраняя накладные расходы от парсинга (parsing –
синтаксический анализ) SQL-предложений в базе данных.
Использование внешних таблиц
Появившийся в Oracle9i механизм внешних таблиц предлагает возможность определения таблицы в базе данных, а хранение табличных данных отдельно от нее, вне базы данных. До Oracle Database 10g внешние таблицы могли быть использованы только как таблицы для чтения. Другими словами, если вы создаете внешнюю таблицу для XML-файлов, эти файлы могут быть запрошены, а таблица может быть соединена с другими таблицами. Тем не менее, никакие DML операции: INSERT, UPDATE и DELETE не разрешены во внешних таблицах.
ЗАМЕЧАНИЕ
В Oracle Database 10g можно записывать данные во внешние таблицы, используя драйвер ORACLE_DATAPUMP вместо используемого по умолчанию ORACLE_DRIVER.
В Oracle Database 10g можно определить во внешней таблице столбцы VARCHAR2 и CLOB для сохранения XML-документов. В следующем примере показано, как создается внешняя таблица со столбцом CLOB для хранения XML-документов. Во-первых, вам нужно создать DIRECTORY для чтения фалов данных:
CREATE DIRECTORY data_file_dir AS
'D:\xmlbook\Examples\Chapter9\src\xml';
GRANT READ, WRITE ON DIRECTORY data_file_dir TO demo;
Затем надо использовать DIRECTORY для определения внешней таблицы:
CREATE TABLE customer_xt (doc CLOB)
ORGANIZATION EXTERNAL
(
TYPE ORACLE_LOADER
DEFAULT DIRECTORY data_file_dir
ACCESS PARAMETERS
(
FIELDS (lobfn CHAR TERMINATED BY ',')
COLUMN TRANSFORMS (doc FROM lobfile (lobfn))
)
LOCATION ('xml.dat')
)
REJECT LIMIT UNLIMITED;
Далее файл xml.dat
customer1.xml
customer2.xml
Если таблица определена, то можно увидеть следующее:
SQL> DESC customer_xt;
Name Null? Type
----------------------------------------- -------- -------------
DOC CLOB
Затем можно запросить XML-документ, как показано далее:
SELECT XMLType(doc).extract('/Customer/EMAIL')
FROM customer_xt;
Тем не менее, запрос требует время работы на создание XMLType и XPath оценки, этот подход полезен, когда приложения нуждаются лишь в нескольких запросов к XML-данным и не хотят перегружать XML-данные в базу данных. В Oracle Database 10g вы не можете создать внешнюю таблицу, которая содержит предопределенные типы XMLType-столбцов.
Эволюция схем
XML-схем развиваются, когда появляется новые требования для XML-данных. Ваши возможности отображать эти изменения в базе данных во многом зависит от памяти хранения.
Если используются реляционные таблицы, то можно изменить структуру таблицы и обновить XML-представления для отражения нового отображения из XML в реляционные таблицы. Если используются CLOB XMLType, то новые XML-данные могут быть вставлены напрямую, так как эта память позволяет вам согласовано сохранять XML в разных XML-схемах. Однако для XML Schema, базируемых на XMLType, эволюция их схем – это очень дорогостоящий процесс, так как он требует обновления объектно-реляционной структуры XMLType. В Oracle Database 10g этот тип развития ограничен для каждого выполняемого импорта/экспорта данных и использования функции CopyEvolution() из пакета DBMS_XMLSCHEMA.
Наилучшая практика
Если нужно принимать XML-данные и сохранять их в базе данных, то первое, что нужно учесть, - это требует ли ваше приложение заготовки XML-структуры в базе данных. Как мы уже видели в Главе 8, вам нужно взвесить все “за и против” возможностей хранения XML и проанализировать, каким образом хранение повлияет на извлечение и обновление XML-данных. В дополнение, вам иногда нужно выбирать особенную модель XML-хранения для осуществления поддержки получения XML в сочетании с разработкой XML-схемы.
После выбора для вашего приложения правильной модели XML-хранения в следующей секции представлены некоторые указания, что нужно знать, когда XML хранятся в Oracle Database 10g.
Обработка определений типов документов
Хотя DTD не используются для определения структуры памяти хранения для XMLType, Oracle XML DB разрешает все DTD-определения и объекты, определенные или упомянутые во вставленном XML-документе. Это выполняется в процессе вставки XMLType, когда анализируются (parsed) все пришедшие XML-документы. В этом процессе разрешаются все объекты, включая внешние и внутренние, определенные в DTD. Это означает, что все объекты перемещаются вместе со своими реальными значениями и, следовательно, все первоначальные
(оригинальные) объектовые ссылки утрачиваются.
Если вы захотите оставить эти ссылки, вам следует сохранить XML в CLOB, вместо CLOB XMLType. Потом вы можете всякий раз создать временный XMLType из этого CLOB, когда вам понадобится разрешить все объекты и использовать контент XML.
Создание XML Schema-базируемых XMLTypes
Вы можете создавать XML Schema-базируемые XMLTypes, используя функции конструирования XMLType или XMLType.CreateXML() функцию. Однако, когда вы используете эти функции для создания XML Schema-базируемых XMLTypes, XML-документ должен содержать XML-атрибуты SchemaLocation. Иногда XML-документ не содержит таких атрибутов. Как же вы сможете создать XML Schema-базируемый XMLType без изменения оригинального XML-документа?
В Главе8 было показано, что можно использовать функцию XMLType.CreateSchemaBasedXML и специфицировать URL XML схемы, как показано ниже:
INSERT INTO product(id, name, description)
VALUES('xdk', 'XML Developer's Kit',
XMLTYPE('<DESCRIPTION><KEYWORD>xdk</KEYWORD> is a set of
standards-based utilities that helps to build
<KEYWORD>XML</KEYWORD> applications. It contains XDK Java
Components, XDK C Components and XDK C++ Components.
</DESCRIPTION>').CreateSchemaBasedXML('http://xmlns.oracle.com/
xml/content.xsd'));
URL http://xmlns.oracle.com/xml/content.xsd является зарегистрированным URL XML схемы и будет использоваться для сохранения продуктового DESCRIPTION.
Специфицирование пространства имен
Если сохраненный XML-документ имеет пространства имен (namespaces), то все XML-запросы к этому документу должны быть определены для пространства имен, так как <Namespace:Element> - это не одно и то же что <Element> в XML. Обе функции XMLType.existNode() и XMLType.extract() разрешают пользователю специфицировать пространство имен во втором параметре, как показано ниже:
MEMBER FUNCTION existsNode(xpath in varchar2, nsmap in varchar2)
RETURN number deterministic
MEMBER FUNCTION extract(xpath IN varchar2, nsmap IN varchar2)
RETURN XMLType deterministic
В этом случае Xpath требует использования полностью квалифицированных (qualified) XML имен, которые содержат имя элемента и его пространство имен. Например, вы можете вставить XML-документ с двумя декларированными пространствами имен в XMLTypes, как показано ниже:
CREATE TABLE temp (doc XMLType);
DECLARE
v_temp XMLType;
BEGIN
v_temp:= XMLType.createXML('<foo xmlns="http://www.example.com"
xmlns:xsd="http://www.w3c.org/2001/XMLSchema">
<foo_type xsd:type="date">03-11-1998</foo_type>
</foo>');
INSERT INTO temp VALUES(v_temp);
END;
Чтобы запросить этот документ, вы можете определить пространство имен и его префикс во втором параметре функции XMLType.extract() и квалифицировать XPath, используя префикс, как показано в следующем SQL-запросе:
SELECT a.doc.extract('/a:foo/a:foo_type',
'xmlns:a="http://www.example.com"')
FROM temp a;
Результатом будет:
<foo_type xmlns="http://www.example.com"
xmlns:xsd="http://www.w3c.org/2001/
XMLSchema" xsd:type="date">03-11-1998</foo_type>
ЗАМЕЧАНИЕ
Если вы не используете квалифицированное имя пространства имен в XPath после предоставленных пространств имен, вы получите [сообщение] ORA-31013: Invalid XPath expression error.
Если у вас есть несколько пространств имен, то можно составить из них список, используя второй параметр функций XMLType.existNode() и XMLType.extract() и разделить их пробелами, как показано в следующем примере:
SELECT a.doc.extract('/a:foo/a:lastupdate/@b:type',
'xmlns:a="http://www.example.com"
xmlns:b="http://www.w3c.org/2001/XMLSchema"') AS result
FROM temp a;
RESULT
--------------------------------------------------
date
ВЫВОДЫ
В этой главе рассматривались разнообразные опции XML-памяти и соответствующие им стратегии загрузки в Oracle Database 10g. Таблица 9-1 показывает взаимодействие между XML-памятью хранения и функциональностью предложенных XML-утилит для загрузки данных. Вы можете выбрать одну из этих утилит или использовать SQL- или PL/SQL- интерфейсы для загрузки XML-документов в базу данных Oracle.
Утилиты |
Функцио-
нальность |
Реляцинное хранилище с XMLType представлениями |
Таблицы XMLType |
XMLType столбцы |
SQL*Loader |
Утилита командной строки |
Ограниченная поддержка |
Да |
Да |
XML SQL Utility |
Утилита командной строки и программный Java- и PL/SQL-интерфейс |
Да |
Да |
Да |
TransX Utility |
Утилита командной строки и программный Java- интерфейс |
Да |
Да |
Да |
XSQL Servlet |
Утилита командной строки и программный Java- и HTTP- интерфейсы, подготовленные во встроенных обработчиках |
Да |
Да |
Да |
HTTP/WebDAV |
HTTP/WebDAV директории |
Нет |
Да, но таблица требует создания таблицы по умолчанию, до того как XML-схема будет зарегистрирована
|
Нет |
FTP Interfaces |
FTP -интерфейсы |
Нет |
Да, но таблица требует создания таблицы по умолчанию, до того как схема будет зарегистрирована |
Нет |
Таблица 9-1. Хранение XML-данных и утилиты загрузки данных