Опубликован: 28.12.2011 | Уровень: для всех | Доступ: свободно
Лекция 11:

Объектные типы данных в Oracle

< Лекция 10 || Лекция 11: 1234 || Лекция 12 >
Преобразование табличных данных в тип XMLTYPE

Ряд функций, объединенных названием SQL/XML в стандарте SQL:2003 (другое название — SQLX), позволяет просто осуществлять преобразование обычных табличных данных в формат XML. В Oracle реализованы следующие функции из этого стандартного набора:

  • XMLELEMENT
  • XMLATTRIBUTES
  • XMLAGG
  • XMLCONCAT
  • XMLFOREST
  • XMLPI[10.2-]
  • XMLCOMMENT[10.2-]
  • XMLROOT[10.2-]
  • XMLSERIALIZE[10.2-]
  • XMLPARSE[10.2-]

[10.2-] начиная с версии 10.2

Вдобавок к этому Oracle SQL содержит ряд расширений SQL/XML и собственных функций для выполнения подобных преобразований:

  • XMLCOLATTVAL
  • SYS_XMLGEN (распространяется на строки)
  • SYS_XMLAGG (распространяется на группы GROUP BY)
  • XMLSEQUENCE (только курсорный вариант)
  • XMLCDATA[10.2-]

[10.2-] начиная с версии 10.2

Следующие примеры поясняют действие некоторых из перечисленных функций:

SET LONG 2000
SELECT XMLELEMENT ( "employee", ename ) AS employee
FROM emp;
SELECT
  XMLELEMENT (
    "employee"
  , XMLATTRIBUTES ( ename AS "name", comm AS "commission" )
  ) AS employee 
FROM emp;
SELECT
  XMLELEMENT (
    "employee"
  , XMLFOREST ( ename AS "name", comm AS "commission" )
  ) AS employee
FROM emp;
SELECT
  XMLELEMENT (
    "employee"
  , XMLCOLATTVAL ( ename AS "name", comm AS "commission" )
  ) AS employee
FROM emp;
SELECT
  XMLELEMENT (
    "department"
  , XMLATTRIBUTES ( deptno AS no )
  ) AS department
, XMLAGG ( XMLELEMENT ( "employee", ename ) ) AS employees
FROM emp
GROUP BY deptno
;
Обратите внимание, что в результатах выдаются поля типа XMLTYPE:
CREATE TABLE xtable ( n ) 
AS 
SELECT XMLELEMENT ( "name", ename ) FROM emp
;
DESCRIBE xtable

Тип ANYDATA

Имеется начиная с версии 9. Позволяет хранить в столбце таблицы данные одновременно разных типов. Используется с объектным типом ANYDATA, имеющим свои конструкторы и методы.

Пример:

CREATE TABLE t ( x ANYDATA );
INSERT INTO t VALUES ( ANYDATA.CONVERTNUMBER   ( 5 ) );
INSERT INTO t VALUES ( ANYDATA.CONVERTDATE     ( SYSDATE ) );
INSERT INTO t VALUES ( ANYDATA.CONVERTVARCHAR2 ( 'hello world' ) );
SELECT t.x.GETTYPENAME ( ) typename FROM t t;
INSERT INTO t VALUES (
  ANYDATA.CONVERTOBJECT ( address_type ( '789012', 'Murmansk' ) )
);

Метода извлечения значения нефиксированного типа в SQL не предусмотрено, и извлечение приходится программировать в два захода: сначала узнать реальный тип значения, а потом уже применить соответствующий типу метод извлечения. Пример ниже подсказывает, как можно при желании составить функцию выборки данного, доступную в SQL, а не только в программе:

SET SERVEROUTPUT ON
DECLARE 
 val     VARCHAR2 ( 30 );
 anumber ANYDATA;
BEGIN
 SELECT t.x INTO anumber
 FROM   t t 
 WHERE  t.x.GETTYPENAME ( ) = 'SYS.NUMBER'
 -- в нашей таблице такая строка единственная
 ;
 DBMS_OUTPUT.PUT_LINE ( 'Ret code: ' || anumber.GETNUMBER ( val ) );
 DBMS_OUTPUT.PUT_LINE ( 'A number: ' || val );
END;
/

Методы типа ANYDATA описаны в документации по Oracle.

Тип ANYDATA, как и XMLTYPE, находит употребление во внутренней организации БД. В частности он используется в построении внутренних "автоматических очередей", лежащих в основе "потоков данных", используемых, в свою очередь, для автоматического переноса данных в Oracle.

< Лекция 10 || Лекция 11: 1234 || Лекция 12 >
Ярослав Прозоров
Ярослав Прозоров

В лекции № 7 "Введение в Oracle SQL" в подразделе "Несамостоятельность группировки с обобщениями ROLLUP, CUBE и GROUPING SETS"  представленная таблица сравнения содержит ошибки - окончания запросов пропущены. Видимо, ошибки вызваны некорректным переносом материала лекции.

Володимир Миколайчук
Володимир Миколайчук
Помогите разобраться поетапно с логикой запроса
-------TOOLS
NAME PRICE TYPE
drill 155 A
sawzall 192 N
mitre saw 292 M
router 86 I
RAD 145 M
jigsaw 128 I
screwdriver 77 P
------TOOL_TYPES
TYPE USAGE
A Always
I Often
M Sometimes
N Rarely
P Never

Запрос SQL:
SELECT t.type, SUM(t.price)
FROM tools t
GROUP BY t.type
HAVING SUM(t.price) >= (SELECT AVG(price)
FROM tools
WHERE type IN (SELECT type
FROM tool_types
WHERE usage = 'Often'));

И сколько строк он все таки вернет
Жанбек Сарсенов
Жанбек Сарсенов
Россия, Москва, Московский Государственный Университет имени Ломоносова М.В., 2002