Статьи

Програмування на XML для DB2: Частина 2. Використання вбудованої в базу даних підтримки XML у вашій архітектурі додатків

  1. Серія контенту:
  2. Цей контент є частиною серії: Програмування на XML для DB2
  3. Основи XML для баз даних
  4. Малюнок 1. Зберігання змішані даних в DB2
  5. Лістинг 1. Таблиці
  6. Лістинг 2. Вставка з Java-програми
  7. Малюнок 2. Логічне уявлення зберігання змішаних даних в DB2
  8. Перенесення логіки додатка в базу даних
  9. Заміна коду програми запитом в DB2
  10. Малюнок 3. Об'єднання двох стовпців XML
  11. Малюнок 4. Результат запиту
  12. Лістинг 4. Запит до двох стовпчиках XML в Viper 2
  13. Порівняння запитів бази даних і коду програми на Java
  14. Створення збереженої процедури
  15. Лістинг 5. Створення процедури
  16. приклад складніше
  17. Лістинг 6. Процедура, яка також вважає страховку для кожного товару
  18. За та проти
  19. Малюнок 5. З'єднання реляційних і XML-стовпців
  20. Лістинг 7. Передача параметрів часу виконання SQL, вставленого в вираз XQuery
  21. висновок
  22. Ресурси для скачування

Програмування на XML для DB2

Серія контенту:

Цей контент є частиною # з серії # статей: Програмування на XML для DB2

https://www.ibm.com/developerworks/ru/views/global/libraryview.jsp?series_title_by=Программирование+на+xml+для+db2

Слідкуйте за виходом нових статей цієї серії.

Цей контент є частиною серії: Програмування на XML для DB2

Слідкуйте за виходом нових статей цієї серії.

За останню пару років статус XML в базах даних виріс з тимчасового робочого до повноправного громадянина. Йому більше не доводиться мімікрувати, щоб вписатися в реляційний світ. Він гордо зберігає своє ієрархічне спадщина, навіть коли використовує міць і стійкість бази даних реляційного світу. Насправді деякі з його реляційних сусідів самі обзавелися техніками, за допомогою яких вони стають схожими на XML, щоб використовувати багаті можливості ієрархічної моделі XML.

У цій статті показано, як нове середовище зберігання XML і запитів поєднуються з моделлю даних XML з першій частині . Ви побачите, чому схеми вашої бази даних стають простіше і природніше, коли ви адаптуєте до нової заснованої на XML архітектурі розробки додатків. Також показано, чому запити XML-даних в базі даних не відрізняються від запитів даних в додатку. І, нарешті, ви дізнаєтеся, як поєднувати реляційні дані з XML-даними, щоб об'єднати сильні сторони обох технологій.

Основи XML для баз даних

Хоча більшість поширених реляційних баз даних надають деяку підтримку для XML, підтримка pureXML ™ в DB2 набагато надійніше і ефективніше, що робить її ідеальною базою даних для тестування програмної моделі XML. У цій статті я розповім, як використовувати цю поліпшену підтримку XML в базах даних при побудові архітектури додатків.

DB2 дозволяє зберігати, запитувати, обслуговувати і публікувати:

  • реляційні дані - SQL
  • реляційні дані у вигляді XML - SQL / XML
  • XML-дані - XQuery
  • змішані дані (реляційні та XML) - SQL / XML і XQuery
Малюнок 1. Зберігання змішані даних в DB2

Зберігання XML в базі даних

Головною перевагою підтримки XML в реляційної базі даних є те, що ви можете зберігати як реляційні, так і XML-дані в одній таблиці. І хоча насправді XML зберігається в ієрархічному (деревоподібному) форматі, логічно в таблиці бази даних він відображається в одному стовпці (як CLOB або BLOB).

На прикладі об'єктів даних з першої частини ви побачили, що існує дві таблиці, що містять принаймні по два стовпці.

Лістинг 1. Таблиці
CREATE TABLE CUSTOMER_TABLE (CUSTOMERID CHARACTER (12) NOT NULL, CUSTXML XML NOT NULL, CONSTRAINT CC1183665042494 PRIMARY KEY (CUSTOMERID)) CREATE TABLE PURCHASE_TABLE (CUSTOMERID CHARACTER (12) NOT NULL, ITEMXML XML NOT NULL, CONSTRAINT CC1183665244645 FOREIGN KEY (CUSTOMERID) REFERENCES CUSTOMER_TABLE (CUSTOMERID) ON DELETE CASCADE ON UPDATE NO ACTION ENFORCED ENABLE QUERY OPTIMIZATION)

З наведених вище тверджень очевидно, що зберігання об'єкта даних програми вигляді XML-даних сильно спрощує реляційні схеми. Плюс до того, оскільки інфраструктура все ще реляційна, це дозволяє використовувати для XML-даних такі перевірені можливості реляційної СУБД, як тригери, обмеження і зовнішні ключі.

Так як логічно XML-стовпець відображається так само, як стовпець ARCHAR, CLOB або BLOB, функції INSERT для них також будуть схожі.

insert into CUSTOMER_TABLE values ​​( 'hardeep', '<Customer customerid = "hardeep" firstname = "hardeep" lastname = "singh" />')

Або, якщо б ви робили вставку з програми Java ™:

Лістинг 2. Вставка з Java-програми
String insertsql = "insert into PURCHASE_TABLE values ​​(?,?)"; PreparedStatement iStmt = connection.prepareStatement (insertsql); File inputfile = new File (filename); // filename is the path of the XML file long filesize = inputfile.length (); BufferedReader in = new BufferedReader (new FileReader (inputfile)); iStmt.setCharacterStream (1, in, (int) filesize); int rc = iStmt.executeUpdate ();

Щоб краще зрозуміти зберігання змішаних даних, подивимося, як логічно представлені XML-дані для зберігання в реляційній базі даних.

Зауваження: Навіть якщо технологія фізичного зберігання XML відрізняється у різних постачальників реляційних баз даних, логічне уявлення у них схоже.

Малюнок 2. Логічне уявлення зберігання змішаних даних в DB2

запит XML

Коли ви розвертаєте схему моделі бази даних, ви бачите реляційні таблиці і стовпчики. При подальшому розгортанні XML-стовпця схема змінюється з реляційної моделі на ієрархічну для XML. Тепер, якщо ви забудете про те, що у вас є дві схеми, реляційна і XML-схема, і будете розглядати їх як одну, ви зможете вільно по об'єднаній схемою і робити в ній запити.

Якщо ви хочете отримати дані з шпальти CUSTXML таблиці CUSTOMER_TABLE з об'єднаної схеми, показаної в лістингу 1, в якості запиту ви повинні вказати шлях до колонку CUSTXML.

SELECT CUSTXML FROM CUSTOMER_TABLE where customerid = 'hardeep';

Цей запит поверне дані з шпальти CUSTXML для користувача з ім'ям hardeep.

Тепер розглянемо випадок, коли нам потрібні дані користувача, де прізвище (lastname) користувача - сингх (singh). Тоді нам треба визначити шлях до атрибуту lastname в кожному XML-документі (CUSTOMER_TABLE.CUSTXML/Customer/@lastname) і перевірити, чи є там значення "singh".

В ідеальному світі запит був би таким: Select * from CUSTOMER_TABLE where CUSTXML / Customer / @ lastname = 'singh'. Однак в реальному світі нам треба сформулювати його так, щоб він був зрозумілий процесору запитів бази даних. У світ баз даних був введений новий мову, XQuery, який можна використовувати для запиту XML-документів. У SQL були додані нові функції, які розуміють цей нову мову і що з'єднують ці два світи. В результаті запит на пошук користувача з прізвищем singh буде виглядати так:

select CUSTXML from CUSTOMER_TABLE where xmlexists ( '$ cust / Customer [@ lastname = "singh"]' passing CUSTXML AS "cust")

Або, якщо ви робите виклик з програми Java, застосовуючи параметризрвані запит:

select CUSTXML from CUSTOMER_TABLE where xmlexists ( '$ cust / Customer [@ lastname = $ lname]' passing CUSTXML AS "cust", cast (? as VARCHAR (12)) as "lname")

Коли ви розберетеся з дивною синтаксисом передачі параметрів функцій SQL / XML, ви виявите, що для нескладних змішаних запитів реляційних і XML-даних XML-запити в основному містять вирази XPath. Це дуже схоже на те, що ми робили для рівня додатки (в першій частині) для моделі даних XML, де більшу частину коду становили виклики XPath до оболонки об'єктної моделі документів (DOM), призначені для запитів і управління XML-даними.

Зауваження: В Viper 2 була дещо спрощена передача параметрів деяких функцій SQL / XML. Наприклад, в попередньому запиті в операторі передачі XMLExists не вказується стовпець CUSTXML.

select CUSTXML from CUSTOMER_TABLE where xmlexists ( '$ CUSTXML / Customer [@ lastname = $ lname]' passing cast (? as VARCHAR (12)) as "lname")

Перенесення логіки додатка в базу даних

XQuery має всі елементарні функції більшості високорівневих мов (if-then-else, for, змінні, функції і арифметичні оператори). Це дає можливість вбудовувати бізнес-логіку в запит. Крім того, ця мова має функціональність, відповідну перетворенням XSLT, тому XQuery дозволяє не тільки запитувати XML, а й перетворювати XML-результат прямо в базі даних.

Скористайтеся прикладом Customer для моделі даних XML з першої частини.

<Customer customerid = "" firstname = "" lastname = ""> <Items> <Item ID = "" description = "" purchaseDate = "" price = "" /> </ Items> </ Customer>

Заміна коду програми запитом в DB2

Замість того щоб об'єднувати XML-дані на рівні додатку, ви можете зробити те ж саме в базі даних за допомогою одного запиту SQL / XML. Використовуємо з'єднання один-ко-многим для таблиць CUSTOMER_TABLE.CUSTXML/Customer/@customerid і PURCHASE_TABLE.ITEMXML/Customer/@customerid.

Малюнок 3. Об'єднання двох стовпців XML
Лістинг 3. Запит до двох стовпчиках XML
values ​​(xmlquery ( 'for $ Customer in db2-fn: xmlcolumn ( "CUSTOMER_TABLE.CUSTXML") / Customer where $ Customer / @ customerid = $ customerid return <Customer customerid = "{$ Customer / @ customerid}" firstname = "{ $ Customer / @ firstname} "lastname =" {$ Customer / @ lastname} "> {for $ Customer0 in db2-fn: xmlcolumn (" PURCHASE_TABLE.ITEMXML ") / Customer where $ Customer0 / @ customerid = $ Customer / @ customerid return $ Customer0 / Item} </ Customer> 'passing cast (? AS varchar (255)) as "customerid"))

В результаті отримаємо XML-дані для всіх товарів, куплених користувачем hardeep:

Малюнок 4. Результат запиту

У попередньому запиті нам довелося створювати зовнішній елемент Customer і додавати атрибути з даних стовпця CUSTXML. В DB2 Viper 2 (бета) є підтримка оновлюють виразів XQuery, що дозволяє змінювати XML-документ і позбавляє від необхідності створювати зовнішній елемент Customer. Замість цього використовуйте відповідний елемент з таблиці customer і додавайте товари з таблиці purchase як нащадків.

Лістинг 4. Запит до двох стовпчиках XML в Viper 2
values ​​(xmlquery ( 'for $ Customer in db2-fn: xmlcolumn ( "CUSTOMER_TABLE.CUSTXML") / Customer let $ items: = (<Items> {for $ Customer0 in db2-fn: xmlcolumn ( "PURCHASE_TABLE.ITEMXML") / Customer where $ Customer0 / @ customerid = $ Customer / @ customerid return $ Customer0 / Item} </ Items>) where $ Customer / @ customerid = $ customerid return transform copy $ cust: = $ Customer modify (do insert $ items as last into $ cust) return $ cust 'passing hardeep as "customerid"))

У попередніх запитах ми не тільки шукали, витягували і об'єднували частини XML-документів, що зберігаються в базі даних, але і перетворювали отриманий XML, додаючи в нього нові елементи. До того ж користувач hardeep був неявно приведений до типу XML (xs: string).

Порівняння запитів бази даних і коду програми на Java

Якщо ви порівняєте наведені вище запити з Java-кодом з першої частини (Лістинг 6. Переписування додатки з використанням моделі XML), то побачите, що логіка у них дуже схожа.

  1. Вибираємо інформацію про користувача (Customer) з таблиці CUSTOMER_TABLE.
  2. Створюємо елемент для товарів (Items) і шукаємо по всім товарам, купленим користувачем з таблиці PURCHASE_TABLE.
  3. Повторюємо для кожного товару з вибраного списку і додаємо в елемент Items.
  4. Додаємо елемент Items до елементу Customer.

Створення збереженої процедури

Щоб відокремити бізнес-логіку від коду програми в базі даних, можна створити збережену процедуру для цього запиту.

Лістинг 5. Створення процедури
CREATE PROCEDURE customerItems (IN custid varchar (12)) DYNAMIC RESULT SETS 1 LANGUAGE SQL BEGIN DECLARE c_cur CURSOR WITH RETURN FOR values ​​(xmlquery ( 'for $ Customer in db2-fn: xmlcolumn ( "CUSTOMER_TABLE.CUSTXML") / Customer let $ items : = (<Items> {for $ Customer0 in db2-fn: xmlcolumn ( "PURCHASE_TABLE.ITEMXML") / Customer where $ Customer0 / @ customerid = $ Customer / @ customerid return $ Customer0 / Item} </ Items>) where $ Customer / @ customerid = $ customerid return transform copy $ cust: = $ Customer modify (do insert $ items as last into $ cust) return $ cust 'passing custid as "customerid")) OPEN c_cur; END

Заміна коду програми викликом процедури,

Тепер код додатка викликає збережену процедуру в DB2 і передає XML в оболонку DOM. Код додатка для моделі XML з першої частини (Лістинг 6. Переписування додатки з використанням моделі XML) зменшиться до нижченаведеного:

2. ResultSet dbResult = dbstmt.executeQuery ( "call customerItems (" + custid + ")" 3. XMLParse customerXML = new XMLParse (dbResult. GetString (1));

приклад складніше

Тепер розглянемо більш складний сценарій, в якому буде обчислюватися страховка для кожного товару. Щоб зробити сценарій цікавіше, страховка буде не тільки змінюватися щодня, але і залежати від ціни. Це означає, що нам треба передати в запит не тільки параметр customerid, але також і розмір страховки. Тепер припустимо, що ми запитуємо свіжі дані про розмір страховки кожен день з Web-сервісу компанії-страховика. Ця інформація надходить у вигляді XML-документа.

<Insurance> <rate price = "100" currency = "$" rate = ". 02" /> <rate price = "500" currency = "$" rate = ". 018" /> <rate price = "" currency = "$" rate = ". 015" /> </ insurance>

Ми можемо змінити попередню збережену процедуру, щоб обчислювати розміри страховки.

Лістинг 6. Процедура, яка також вважає страховку для кожного товару
CREATE PROCEDURE customerItemsWithInsurance (IN custid varchar (12), rate XML) DYNAMIC RESULT SETS 1 LANGUAGE SQL BEGIN DECLARE c_cur CURSOR WITH RETURN FOR values ​​(xmlquery ( 'for $ Customer in db2-fn: xmlcolumn ( "CUSTOMER_TABLE.CUSTXML") / Customer let $ items: = (<Items> {for $ Customer0 in db2-fn: xmlcolumn ( "PURCHASE_TABLE.ITEMXML") / Customer let $ insurance: = <insurance currency = "{($ rate // rate [@ price =" "] / @ currency)}"> {(if ($ Customer0 / Item / @ price> 500) then ($ Customer0 / Item / @ price * $ rate // rate [@price = ""] / @ rate) else (if ($ Customer0 / Item / @ price> 100) then ($ Customer0 / Item / @ price * $ rate // rate [@ price = "500"] / @ rate) else ($ Customer0 / Item / @ price * $ rate // rate [@ price = "100"] / @ rate)))} </ insurance> where $ Customer0 / @ customerid = $ Customer / @ customerid return transform copy $ item: = $ Customer0 / Item modify (do insert $ insurance as last into $ item) return $ item} </ Items>) where $ Customer / @ customerid = $ customerid return transform copy $ cust: = $ Customer modify (do insert $ items as last into $ cust) retur n $ cust 'passing custid as "customerid", rate as "rate")); OPEN c_cur; END

У виклику до збереженій процедурі задаються два параметра часу виконання - customerid і insurance XML.

call customerItemsWithInsurance (?,?)

З попереднього прикладу видно, що якщо дані, з якими ми працюємо в базі даних, знаходяться в XML-форматі, то можна застосувати міць мови XQuery для реалізації більш складної бізнес-логіки, ніж дозволяв SQL сам по собі. Зрозуміло також, що XML, який ми використовували в запиті, не обов'язково повинен знаходитися в базі даних. Таким чином, XML-дані, які беруть участь в SQL / XML-запиті, або можуть зберігатися в базі даних в "чистій" (ієрархічної) формі, яку можна створити за допомогою SQL / XML-функцій, або ці дані можна передавати як параметри часу виконання запиту. Межі між базою даних і сервером додатка потроху стираються.

За та проти

Як і у будь-якої нової технології, тут можливі проблеми зростання. Деякі труднощі виникають через те, що це тільки перші версії реалізацій, інші через інертність користувачів, які не хочуть міняти правильно і надійно працюють звичні технології.

  1. Незважаючи на поліпшення, продуктивність до сих пір менше, ніж для реляційних даних.
  2. XQuery - нова мова, і деякі SQL / XML- функції мають такий синтаксис, до якого ще треба звикнути.
  3. В даний час більшість наявних даних зберігаються в реляционном форматі.
  4. Найбільш важливим є те, що ми створюємо новий спосіб завдання бізнес-додатків і схем даних, який відрізняється від підходу, використовуваного в даний час, - об'єктно-орієнтованих програм і нормалізованих реляційних схем.
  5. У нас є не так багато інструментів, які могли б налагоджувати і оптимізувати такі запити для поліпшення продуктивності.

Протиставити цим аргументам можна той факт, що нова модель дозволяє більш природно управляти даними. Бізнес-дані зберігаються і обслуговуються в незмінному вигляді, як на рівні додатку, так і на рівні бази даних, і, як ви побачите в третій частині, навіть на клієнтському рівні.

  • Незалежно від мови зовнішнього коду (Java, XQuery, JavaScript, PHP) мову для навігації по XML-документу завжди один (XPath) на всіх рівнях.
  • Хоча існуючі дані є реляційними, їх можна легко запитувати і перетворювати до формату XML за допомогою деяких нових SQL / XML-функцій, представлених в Viper II. Подивіться на приклад з першої статті: "Другий випадок - Всі дані зберігаються в реляційній базі даних". Запит можна спростити, використовуючи нову функцію XMLROW, представлену в Viper 2. Select XMLROW (customerid, firstname, lastname OPTION as attributes ROW Customer) from customer_table where customerid =?

    Ви також можете створювати з'єднання між реляційними та XML-даними. В даному сценарії, якби у нас була таблиця з описами для придбаних товарів і вона була б реляційної, ми могли б отримати опис продукту для кожного придбаного товару, встановивши з'єднання за ідентифікатором товару.

    Малюнок 5. З'єднання реляційних і XML-стовпців
    Select details, weight from SQLPRODUCT, ITEM_TABLE where xmlexists ( '$ itemxml / item [@ itemid = $ pid]' passing ITEM_TABLE.ITEMXML AS "itemxml", SQLPRODUCT.PID AS "pid")

    В DB2 9 ви можете передавати параметри часу виконання запиту XQuery, вставленого в вираз SQL, за допомогою оператора passing, але не можете зробити те ж саме для SQL, вставленого в вираз XQuery. В Viper 2 такого обмеження немає, і ви можете передавати параметри часу виконання в реляційні запити всередині XQuery.

    Лістинг 7. Передача параметрів часу виконання SQL, вставленого в вираз XQuery
    values ​​(xmlquery ( 'for $ Customer0 in db2-fn: xmlcolumn ( "PURCHASE_TABLE.ITEMXML") / Customer where $ Customer0 / @ customerid = $ custid return ($ Customer0 / Item, db2-fn: sqlquery (' 'select xmlrow ( details, description, weight option ROW "description") from sqlproduct where pid = parameter (1) '', $ Customer0 / Item / @ ID)) 'passing cast (? AS varchar (255)) as "custid"))

    Таким чином, навіть якщо одні дані зберігаються в реляційних таблицях, а інші в XML-форматі, ви тепер можете виконувати динамічні з'єднання між XML і реляційними даними в запитах SQL, XQuery або в обох одночасно.

  • У багатьох випадках навіть продуктивність не буде великою проблемою, так як:
    • Ви можете створювати засновані на виразах XPath індекси для XML-документів, що зберігаються в базі даних. create index custfname on customer_table (info) generate key using xmlpattern '/ Customer / @ firstname' as sql varchar (64)
    • Кількість необхідних з'єднань зменшується, тому що схеми баз даних стають простіше.
    • Можна скоротити введення / виведення, так як ви можете керувати даними в запиті ще до того, як відправите їх у додаток.
    • Ви завжди можете отримати інформацію про ключах з XML-документа в реляційні стовпці за допомогою SQL / XML-функцій, таких як XMLTable, і створити для них реляційні індекси.
    • Для XML-документів можна створювати індекси текстового пошуку.

висновок

XML увійшов в наше життя надовго і всерйоз. Більшість індустріальних і урядових організацій стандартизують свої XML-схеми і наполягають на використанні електронних документів, які відповідають цим схемам. З огляду на, що обмін даними B2B (бізнес-бізнес) по мережі відбувається в форматі XML, чому б не зберігати ці дані в тому ж форматі (pureXML) в базі даних? Маючи дані в XML, ви можете індексувати їх, запитувати, перевіряти на відповідність схемі, управляти ними, перетворювати і оновлювати їх за допомогою мови XQuery і стандартного SQL / XML. У міру того як ви переносите в запити логіку додатка, ваша база даних стає активною дійовою особою в світі сервіс-орієнтованої архітектури, публікуючи збережені процедури як Web-сервіси та XML-канали.

"Старий порядок речей іде, даючи місце новому." смерть Артура

Ресурси для скачування

Схожі тими

  • Оригінал статті " Program with XML for DB2, Part 2: Leverage database support for XML in your application architecture "(EN).
  • " Успіх ISV з DB2 Viper (ISV success with DB2 Viper) (EN) (developerWorks, березень 2006 року): підготуйте Ваші програми, програми сценарії до переносу в DB2 Viper.
  • Читайте інші статті за технологіямі DB2 и XML . (EN)
  • Швидкий и успішній старт в DB2 Viper (Get off to a fast start with DB2 Viper) (DeveloperWorks, березень 2006 року): як створювати об'єкти бази даних для роботи з даними XML і як заповнювати базу даних DB2 даними XML.
  • DB2 і XML: Запит XML-даних за допомогою SQL (Query DB2 XML data with SQL) (DeveloperWorks, березень 2006 року):.): Як запитувати дані, що зберігаються в стовпцях XML, за допомогою XQuery.
  • Запит XML-даних за допомогою мови XQuery (Query DB2 XML data with XQuery) (DeveloperWorks, квітень 2006 року): вивчіть основи запитів даних в DB2 за допомогою XQuery.
  • Програмування XML за допомогою PHP і Ajax (XML Programming with PHP and Ajax) (EN): використання можливостей XML в DB2 9 для роботи в сервіс-орієнтованої архітектури та інших бізнес-сценаріях.
  • Спільне використання вбудованої підтримки XML в DB2 і PHP (Use DB2 native XML with PHP) (DeveloperWorks, листопад 2005 року): дізнайтеся, як ефективно використовувати вбудовану підтримку XML майбутньої версії DB2 Universal Database для Linux, UNIX і Windows для спрощення коду додатків і реляційних схем.
  • Вбудована підтримка XML в DB2 Universal Database (Native XML support in DB2 Universal Database) (EN): порівняйте нову підтримку XML в DB2 з традиційною реляційної технологією баз даних.
  • Завантажте відкриту бета-версію DB2 Viper 2 .
  • У розділі Information Management на developerWorks ви дізнаєтеся більше про DB2 і знайдете технічну документацію, статті з інструкціями, навчальні посібники, матеріали для завантаження, інформацію про продукти і багато іншого.
  • Використовуйте в своєму наступному проекті ознайомлювальне ПО IBM , Яке можна завантажити прямо з сайту developerWorks. (EN)

Підпішіть мене на ПОВІДОМЛЕННЯ до коментарів

Jsp?
2. Select XMLROW (customerid, firstname, lastname OPTION as attributes ROW Customer) from customer_table where customerid =?
З огляду на, що обмін даними B2B (бізнес-бізнес) по мережі відбувається в форматі XML, чому б не зберігати ці дані в тому ж форматі (pureXML) в базі даних?

Новости