PL/SQL таблицы.
От: SHorrty Россия  
Дата: 19.05.04 06:06
Оценка:
Кто нибудь сталкивался с необходимостью преобразования сложных PL/SQL таблиц в XML — формат?

То есть, на входе что-то вроде:


  TYPE T_REC IS RECORD(a NUMBER, и DATE);
  TYPE T_TAB IS TABLE OF T_REC;

На выходе — SYS.XmlType.


Какие решения были найдены?
И есть ли в Oracle9i средства формирования XML данных не для результатов выборки, а для данных, находящихся в памяти?
Re: PL/SQL таблицы.
От: Denis Popov Россия http://picasaweb.google.com/denislpopov
Дата: 19.05.04 08:14
Оценка:
Здравствуйте, SHorrty, Вы писали:

SH>Кто нибудь сталкивался с необходимостью преобразования сложных PL/SQL таблиц в XML — формат?


В качестве варианта — можно работать не с PL/SQL, а с объектными таблицами — из них можно делать запросы и, соответственно, получать XML.
Re[2]: PL/SQL таблицы.
От: SHorrty Россия  
Дата: 19.05.04 08:24
Оценка:
Здравствуйте, Denis Popov, Вы писали:

DP>Здравствуйте, SHorrty, Вы писали:


SH>>Кто нибудь сталкивался с необходимостью преобразования сложных PL/SQL таблиц в XML — формат?


DP>В качестве варианта — можно работать не с PL/SQL, а с объектными таблицами — из них можно делать запросы и, соответственно, получать XML.



В том то и проблема, что надо преобразовывать произвольные структуры....
С объектами — понятно + подвязать еще AnyData и все в поряде будет.
Только даже с ними: я так понял, что генерация XML происходит только для выборки?
То есть, хочешь XML — сделай выборочку... а есть ли операторы, которые возвращают тот же SYS.XmlType, то не на основе выборки, а на основе переданных данных? а то? что-то накладно немного получается каждый раз в табличку лезть..
Re[3]: PL/SQL таблицы.
От: Denis Popov Россия http://picasaweb.google.com/denislpopov
Дата: 19.05.04 08:39
Оценка:
Здравствуйте, SHorrty, Вы писали:


SH>В том то и проблема, что надо преобразовывать произвольные структуры....

SH>С объектами — понятно + подвязать еще AnyData и все в поряде будет.
SH>Только даже с ними: я так понял, что генерация XML происходит только для выборки?


Ну да: есть функция, возвращающая объектную таблицу. Ее результат можно подсунуть тому же DBMS_XMLGEN:

select dbms_xmlgen.getXML('select * from table(cast(my_function as my_table_type))') xml from dual;
Re[4]: PL/SQL таблицы.
От: SHorrty Россия  
Дата: 19.05.04 09:16
Оценка:
Здравствуйте, 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>


Ок. Это я так понимаю, мы в PIPELINE упираемся...
А если вернуться к произвольным коллекциям, с типом не хранимым в БД?
Re[5]: PL/SQL таблицы.
От: Denis Popov Россия http://picasaweb.google.com/denislpopov
Дата: 19.05.04 09:34
Оценка:
Здравствуйте, 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>А если вернуться к произвольным коллекциям, с типом не хранимым в БД?


А где хранится описание этой коллекции, в каком виде?
Re[6]: PL/SQL таблицы.
От: SHorrty Россия  
Дата: 19.05.04 10:06
Оценка:
Здравствуйте, 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 (либо пакет аналогичной направленности) ?
Re[7]: PL/SQL таблицы.
От: Denis Popov Россия http://picasaweb.google.com/denislpopov
Дата: 19.05.04 10:19
Оценка:
Здравствуйте, 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-таблица", по-моему нельзя. Т.е. остаются только объектные таблицы.
Re[8]: PL/SQL таблицы.
От: SHorrty Россия  
Дата: 19.05.04 10:34
Оценка:
Здравствуйте, Denis Popov, Вы писали:



DP>ИМХО нельзя. Собственно, мне самому интересно, можно ли в процедуре указать параметр "абстрактная pl/sql-таблица", по-моему нельзя. Т.е. остаются только объектные таблицы.


Вот и я сомневаюсь....
Re: PL/SQL таблицы.
От: wildwind Россия  
Дата: 22.05.04 14:46
Оценка:
Здравствуйте, SHorrty, Вы писали:

SH>Кто нибудь сталкивался с необходимостью преобразования сложных PL/SQL таблиц в XML — формат?

SH>Какие решения были найдены?
SH>И есть ли в Oracle9i средства формирования XML данных не для результатов выборки, а для данных, находящихся в памяти?

Да, столкнулись недавно. Были рассмотрены многие варианты. В Oracle (9.2) есть следующие способы получить XMLType:
  1. "Вручную": xml := XMLType('<?xml version="1.0" ? <DOC>abc</DOC>');
  2. Из курсора: xml := XMLType(cur);
  3. Через DBMS_XMLGEN. Варианты: из курсора и из текста селекта 'select * from ...'.
  4. Используя DOM API (пакет DBMS_XMLDOM), можно создать документ любой структуры.
  5. Используя функцию SYS_XMLGEN(), можно создать XMLType из экземпляра объектного типа. Опять же, только через select.
  6. Используя SQLX функции: XMLELEMENT(), XMLFOREST(), XMLCONCAT(), XMLAGG(). Достаточно гибко, но тоже через select.
  7. Написать функцию на 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 все еще ищется, так что если кто знает, плз...
  •  
    Подождите ...
    Wait...
    Пока на собственное сообщение не было ответов, его можно удалить.