Здравствуйте, Denis Popov, Вы писали:
DP>Здравствуйте, SHorrty, Вы писали:
SH>>Кто нибудь сталкивался с необходимостью преобразования сложных PL/SQL таблиц в XML — формат?
DP>В качестве варианта — можно работать не с PL/SQL, а с объектными таблицами — из них можно делать запросы и, соответственно, получать XML.
В том то и проблема, что надо преобразовывать произвольные структуры....
С объектами — понятно + подвязать еще AnyData и все в поряде будет.
Только даже с ними: я так понял, что генерация XML происходит только для выборки?
То есть, хочешь XML — сделай выборочку... а есть ли операторы, которые возвращают тот же SYS.XmlType, то не на основе выборки, а на основе переданных данных? а то? что-то накладно немного получается каждый раз в табличку лезть..
SH>В том то и проблема, что надо преобразовывать произвольные структуры.... SH>С объектами — понятно + подвязать еще AnyData и все в поряде будет. SH>Только даже с ними: я так понял, что генерация XML происходит только для выборки?
Ну да: есть функция, возвращающая объектную таблицу. Ее результат можно подсунуть тому же DBMS_XMLGEN:
select dbms_xmlgen.getXML('select * from table(cast(my_function as my_table_type))') xml from dual;
Здравствуйте, SHorrty, Вы писали:
SH>Здравствуйте, Denis Popov, Вы писали:
DP>>Ну да: есть функция, возвращающая объектную таблицу. Ее результат можно подсунуть тому же DBMS_XMLGEN: DP>>
DP>>select dbms_xmlgen.getXML('select * from table(cast(my_function as my_table_type))') xml from dual;
DP>>
SH>Ок. Это я так понимаю, мы в PIPELINE упираемся...
PIPELINED-функции в Oracle 9i появились, а вышеприведенный код пройдет начиная с Oracle8i. Можно попытаться сделать запрос прямо из переменной типа "Объектная таблица", описаной, к примеру, в спецификации пакета. Надо будет проверить, допустимо ли это.
SH>А если вернуться к произвольным коллекциям, с типом не хранимым в БД?
А где хранится описание этой коллекции, в каком виде?
Здравствуйте, Denis Popov, Вы писали:
DP>Здравствуйте, SHorrty, Вы писали:
SH>>Здравствуйте, Denis Popov, Вы писали:
DP>>>Ну да: есть функция, возвращающая объектную таблицу. Ее результат можно подсунуть тому же DBMS_XMLGEN: DP>>>
DP>>>select dbms_xmlgen.getXML('select * from table(cast(my_function as my_table_type))') xml from dual;
DP>>>
SH>>Ок. Это я так понимаю, мы в PIPELINE упираемся...
DP>PIPELINED-функции в Oracle 9i появились, а вышеприведенный код пройдет начиная с Oracle8i. Можно попытаться сделать запрос прямо из переменной типа "Объектная таблица", описаной, к примеру, в спецификации пакета. Надо будет проверить, допустимо ли это.
SH>>А если вернуться к произвольным коллекциям, с типом не хранимым в БД?
DP>А где хранится описание этой коллекции, в каком виде?
Где угодно. Не обязательно, что она объявлена в спецификации.
Вообщем Суть: программер хранит нужные ему данные в созданной под себя коллекции, ему нужно представить эту коллекцию в виде XML:
DECLARE
/* Типы */
TYPE T_REC IS RECORD(n NUMBER, d DATE, с VARCHAR2(300));
TYPE T_TAB IS TABLE OF T_REC;
/* Переменные */
v_Tmp T_TAB;
l_Xml sys.XmlType;
BEGIN
/*
как-то там заполняем таблицу v_Tmp
*/
-- Хотим конвертить v_Tmp в XML
l_Xml := convert_function(v_Tmp);
END;
Встает вопрос, как так можно (и возможно ли вообще ?) организовать функцию convert_function (либо пакет аналогичной направленности) ?
Здравствуйте, SHorrty, Вы писали:
SH>Вообщем Суть: программер хранит нужные ему данные в созданной под себя коллекции, ему нужно представить эту коллекцию в виде XML:
SH>
SH>DECLARE
SH> /* Типы */
SH> TYPE T_REC IS RECORD(n NUMBER, d DATE, с VARCHAR2(300));
SH> TYPE T_TAB IS TABLE OF T_REC;
SH> /* Переменные */
SH> v_Tmp T_TAB;
SH> l_Xml sys.XmlType;
SH>BEGIN
SH> /*
SH> как-то там заполняем таблицу v_Tmp
SH> */
SH> -- Хотим конвертить v_Tmp в XML
SH> l_Xml := convert_function(v_Tmp);
SH>END;
SH>
SH>Встает вопрос, как так можно (и возможно ли вообще ?) организовать функцию convert_function (либо пакет аналогичной направленности) ?
ИМХО нельзя. Собственно, мне самому интересно, можно ли в процедуре указать параметр "абстрактная pl/sql-таблица", по-моему нельзя. Т.е. остаются только объектные таблицы.
DP>ИМХО нельзя. Собственно, мне самому интересно, можно ли в процедуре указать параметр "абстрактная pl/sql-таблица", по-моему нельзя. Т.е. остаются только объектные таблицы.
Здравствуйте, SHorrty, Вы писали:
SH>Кто нибудь сталкивался с необходимостью преобразования сложных PL/SQL таблиц в XML — формат? SH>Какие решения были найдены? SH>И есть ли в Oracle9i средства формирования XML данных не для результатов выборки, а для данных, находящихся в памяти?
Да, столкнулись недавно. Были рассмотрены многие варианты. В Oracle (9.2) есть следующие способы получить XMLType: "Вручную": xml := XMLType('<?xml version="1.0" ? <DOC>abc</DOC>');
Из курсора: xml := XMLType(cur);
Через DBMS_XMLGEN. Варианты: из курсора и из текста селекта 'select * from ...'.
Используя DOM API (пакет DBMS_XMLDOM), можно создать документ любой структуры.
Используя функцию SYS_XMLGEN(), можно создать XMLType из экземпляра объектного типа. Опять же, только через select.
Используя SQLX функции: XMLELEMENT(), XMLFOREST(), XMLCONCAT(), XMLAGG(). Достаточно гибко, но тоже через select.
Написать функцию на Java. Там можно использовать весь Java-арсенал.
Пример, демонстрирующий эти подходы (кроме java), прицепил в виде файла (чтобы не загромождать страницу).
После рассмотрения за и против был выбран DBMS_XMLDOM из-за универсальности и обещанного быстродействия (вроде на C писан). Минусы:
код получается довольно громоздким и малопонятным;
возможны утечки памяти — созданные DOM-документы нужно удалять самостоятельно.
Проблему произвольной структуры решили так:
type CND_rec is record (
c varchar2(2000),
n number,
d date
);
type CND_array is table of rs_cell_t index by varchar2(64);
Вот такая таблица и подается на преобразование в XML. Если хотим конвертнуть одну запись, имена полей будут ключами в таблице. Если имеем набор записей, то к имени поля добавляется номер записи. То есть ключ получается вида <name>[:<row#>]. При этом имена полей и количество записей тоже должны быть известны. SH>С объектами — понятно + подвязать еще AnyData и все в поряде будет. SH>Ок. Это я так понимаю, мы в PIPELINE упираемся... SH>А если вернуться к произвольным коллекциям, с типом не хранимым в БД?
Да, в этом направлении тоже копал... Есть такой трюк: можно создать табличную функцию, возвращающую ANYDATASET. Создается она по-хитрому, только как pipelined и только через интерфейс ODCITable, и может возвращать коллекцию, структура которой соответствует одному из типов, описанных на уровне схемы. То есть, если например имеется 10 вариантов структуры, то для каждого из них надо сделать
create type Type1 as object ( ... );
, и при реализации функции указать, что данные пойдут в таком-то формате. Это можно использовать при обратном преобразовании XML->PL/SQL.
2 All
В 10g ограничение на тип снято, и там можно генерить совершенно произвольные структуры. Однако способ сделать это в 9i все еще ищется, так что если кто знает, плз...