Day 30: Dimension

Learning In HomeOriginal Date: 11 Februari 2009

Data warehousing membutuhkan struktur data khusus yang tidak ditemui di OLTP, salah satunya adalah dimension/dimensi. Contoh dimension antara lain time, product dan customer. Dimensi dapat memiliki hierarki, misalnya, dimensi time dapat di-roll up menjadi quarters, dan quarters dapat di-roll up menjadi years, dan years di-roll up menjadi all years. Analisa data umumnya dimulai dari dimensi dengan hierarki tertinggi dan perlahan-lahan di-drill down sesuai kebutuhan.

Sebagai contoh, terdapat sebuah denormalized table dengan nama times yang memiliki atribut seperti calendar_year, calendar_quarter_number, calendar_month_number, calendar_week_number, dan day_number_in_week, dan lainnya. Aku dapat merepresentasikan hubungan hierarki antar-kolom di tabel tersebut dengan membuat dimensi sebagai berikut:


CREATE DIMENSION LATIHAN_TIMES
  LEVEL year IS 
    (times.calendar_year)
  LEVEL quarter IS 
    (times.calendar_quarter_number)
  LEVEL month IS 
    (times.calendar_month_number)
  LEVEL week IS 
    (times.calendar_week_number)
  LEVEL day IS 
    (times.day_number_in_week)
  HIERARCHY times_rollup (
    day  CHILD OF
    week CHILD OF
    month CHILD OF
    quarter CHILD OF
    year
  );

Untuk melihat keterangan mengenai dimensi yang baru saja aku buat tadi, aku dapat menggunakan perintah:


EXECUTE dbms_dimension.describe_dimension('LATIHAN_TIMES');

Untuk memeriksa apakah dimensi yang baru aku buat valid, aku akan menggunakan API dbms_dimension.validate_dimension(). Tapi sebelum itu, aku akan membuat sebuah tabel DIMENSION_EXCEPTIONS terlebih dahulu dengan menjalankan script %ORA_HOME%\rdbms\admin\utldim.sql. Setelah itu, aku menjalankan kode berikut:


EXECUTE dbms_dimension.validate_dimension('LATIHAN_TIMES', FALSE, TRUE, 'check1');

Aku akan mendapatkan daftar kesalahan di tabel DIMENSION_EXCEPTION. Disini terdapat rowid baris mana yang invalid. Kesalahan yang aku buat adalah hubungan relasi 1:n antara sebuah parent dan anak-anaknya. Sebuah ‘year’ dapat memiliki banyak ‘quarter number’, tetapi sebuah ‘quarter number’ tidak dapat mengandung lebih dari satu parent ‘year’. Untuk itu, aku harus menggunakan id agar mendapatkan quarter number yang unik di setiap year yang ada. Begitu juga dengan hierarki di bawahnya sehingga dimensi-nya kira-kira seperti berikut ini:


DROP DIMENSION LATIHAN_TIMES;

CREATE DIMENSION LATIHAN_TIMES
  LEVEL year IS 
    (times.calendar_year)
  LEVEL quarter IS 
    (times.calendar_quarter_id)
  LEVEL month IS 
    (times.calendar_month_id)  
  LEVEL day IS 
    (times.time_id)
  HIERARCHY times_rollup (
    day  CHILD OF    
    month CHILD OF
    quarter CHILD OF
    year
  );
Iklan

Day 29: Materialized View

Learning In HomeOriginal Date: 10 Februari 2009

Oracle Database selain menawarkan fitur OLTP (Online Transaction Processing), juga mendukung data Warehousing. Secara singkatnya, aku bisa bilang kalau OLTP adalah proses database sehari-hari dimana data di-input oleh user dan disimpan di tabel relational, sedangkan data warehousing adalah proses penyimpanan data untuk keperluan query dan analisa. Ada beberapa karakteristik data warehousing yang berbeda dari OLTP, misalnya, memiliki banyak index, sedikit join, dan tabel yang tidak ter-normalisasi.

Data yang dipakai dalam data warehousing adalah data historical berbulan-bulan atau bertahun-tahun yang lalu. Oleh sebab itu, kebanyakan fact table dalam data warehousing memiliki ukuran yang sangat besar. Salah satu cara untuk meningkatkan performance dalam data warehousing adalah dengan membuat summary. Implementasi tabel summary ini pada database Oracle dapat dicapai dengan menggunakan materialized view. Berikut ini adalah contoh SQL untuk membuat materialized view:


CREATE MATERIALIZED VIEW 
  LOG ON products 
  WITH SEQUENCE, ROWID
  (prod_id, prod_name)
  INCLUDING NEW VALUES;
  
CREATE MATERIALIZED VIEW 
  LOG ON sales 
  WITH SEQUENCE, ROWID
  (prod_id, quantity_sold, amount_sold)
  INCLUDING NEW VALUES;
  
CREATE MATERIALIZED VIEW 
    products_sales
  BUILD IMMEDIATE
  REFRESH FAST
  ENABLE QUERY REWRITE 
  AS
    SELECT 
      p.prod_id,
      sum(quantity_sold) 
        as quantity_sold,
      sum(amount_sold) 
        as amount_sold
    FROM sales s, products p
    WHERE
      s.prod_id = p.prod_id
    GROUP BY
      p.prod_id;

Tabel sales di schema SH (Sales History, demo schema bawaan Oracle Database) adalah tabel yang isinya besar yang mencapai 1.016.271 record. Setiap query yang mengandung SUM, AVG, dan sebagainya yang umum dipergunakan dalam reporting pasti akan menggunakan banyak resource jika harus di-proses ulang setiap kali request. Pada contoh di atas, aku menyertakan klausa ENABLE QUERY REWRITE untuk mengaktifkan query rewrite. Aku juga menyertakan klausa REFRESH FAST. Ini berarti, aku ingin materialized view tersebut nilainya diperbaharui secara otomatis jika ada perubahan pada tabel yang membentuknya, yaitu tabel products dan tabel sales. Perubahan ini akan di-apply secara incremental berdasarkan data dari log yang sudah buat untuk tabel sales dan tabel products sehingga proses refresh bisa lebih singkat.

Materialized view akan dipakai secara otomatis melalui teknik yang disebut query rewrite tanpa perlu referensi ke materialized view bersangkutan di statement SQL. Dengan demikian, operasi materialized view berlangsung secara transparan bagi user yang memberikan statement SQL. Sebuah query SQL akan melalui beberapa proses untuk menentukan apakah ia akan mengalami query rewrite atau tidak. Oracle akan melalui perbandingan full text untuk menentukan apakah query SQL sesuai dengan query di materialized view (perbandingan ini tidak menyertakan whitespace). Jika tidak ketemu, ia akan membandingkan bagian FROM dari query SQL dan query di materialized view. Jika masih belum ketemu juga, maka ia akan menggunakan general query rewrite.

Day 28: Menampilkan Apa Yang Ditemukan Oracle Text

Learning In HomeOriginal Date: 9 Februari 2009

Untuk melihat hasil filter dokumen yang berada dalam format bukan teks, aku dapat menggunakan API ctx_doc.filter seperti contoh berikut:

DECLARE
  hasil_filter CLOB;
BEGIN
  ctx_doc.filter(
    'IDX_DOC_ATTACHMENT', 
    'AAANiLAAEAAAAL/AAA', 
    hasil_filter);
  dbms_output.
    put_line(hasil_filter);
END;
/

Pada contoh diatas, aku menampung hasil filter dari sebuah baris berdasarkan ROWID ke sebuah variabel CLOB. Jika blok di atas dijalankan, aku akan memperoleh isi file MS-WORD (DOC) dalam bentuk HTML.

Untuk mencari tahu kata apa saja yang sesuai dengan ekspresi pencarian, aku dapat menggunakan API ctx_doc.markup seperti pada contoh berikut:


DECLARE
  hasil_markup CLOB;
BEGIN
  ctx_doc.markup(
    'IDX_DOC_ATTACHMENT', 
    'AAANiLAAEAAAAL/AAA',
    'about(exam)',
    hasil_markup, true);
  dbms_output.
    put_line(hasil_markup);
  dbms_lob.
    freetemporary
    (hasil_markup);
END;
/

Contoh di-atas akan memberi tanda pada kata yang mendekati exam, dimana hasil outputnya seperti berikut:


My name is Solid Snake. I’m here to write down something. I hope I can pass the <<<exam>>> in the examination.

Day 27: Index Categori dan Rule di Oracle Text

Learning In HomeOriginal Date: 8 Februari 2009

Setelah menggunakan index CONTEXT di hari sebelumnya, hari ini aku akan mencoba latihan menggunakan index CTXCAT. Aku akan mulai dengan membuat index set terlebih dahulu:


BEGIN
 ctx_ddl.create_index_set
   ('idx_set_barang');
 ctx_ddl.add_index
   ('idx_set_barang', 
    'harga');
 ctx_ddl.add_index
   ('idx_set_barang', 
    'harga,kategori');
 ctx_ddl.add_index
   ('idx_set_barang', 
    'kategori');
END;
/

Aku membuat index dengan menggunakan perintah seperti ini:


CREATE INDEX idx_barang ON tbl_barang(nama)
INDEXTYPE IS CTXSYS.CTXCAT
PARAMETERS ('index set idx_set_barang');

Setelah itu, aku siap mencoba query yang memakai category search, seperti:


SELECT * FROM TBL_BARANG WHERE CATSEARCH(nama, 'Intel', 'harga<3000000') > 0;

Query di atas akan mencari nama yang mengandung kata Intel (case insensitive) dimana harga berada di bawah 3000000. Contoh query lainnya yang memakai category search, misalnya:


SELECT * FROM TBL_BARANG WHERE CATSEARCH(nama, 'intel', 'harga<3000000 and kategori = 3') > 0;


SELECT * FROM TBL_BARANG WHERE CATSEARCH(nama, 'geforce', 'order by harga') > 0;

Selanjutnya, aku akan mencoba memakai index CTXRULE yang dapat dipergunakan untuk klasifikasi teks. Misalnya, aku menyiapkan tabel berikut:


CREATE TABLE TBL_KATEGORI_TEXT (
  ID NUMBER(10),
  KATEGORI VARCHAR2(100),
  EKSPRESI VARCHAR2(100)
);

INSERT INTO TBL_KATEGORI_TEXT VALUES 
 (1, 'Hero', 
  'Spiderman or Wolverine or Dr.Strange');

INSERT INTO TBL_KATEGORI_TEXT VALUES 
 (2, 'Villain', 
  'Octopus or Dr.Doom or Magneto');

CREATE INDEX idx_kategori_text ON 
  tbl_kategori_text (ekspresi) 
  INDEXTYPE IS ctxsys.ctxrule;

Lalu, aku dapat memberikan query berikut:


SELECT kategori FROM TBL_KATEGORI_TEXT WHERE MATCHES(ekspresi, 'dr.doom')>0;

yang akan mengembalikan nilai Villain.

Day 26: Oracle Text

Learning In HomeOriginal Date: 7 Februari 2009

Oracle Text adalah fitur database Oracle yang menangani query yang berkaitan dengan teks. Sebelum menggunakan Oracle Text, aku memastikan user database telah memiliki role CTXAPP, dan berhak menjalankan isi package CTX_CLS, CTX_DDL, CTX_DOC, CTX_OUTPUT, CTX_QUERY, CTX_REPORT, dan CTX_THES.

Aku memiliki beberapa pilihan jenis index saat menggunakan Oracle Text. Untuk meng-index kolom yang terdiri atas teks dalam jumlah besar dan dalam format tertentu, misalnya HTML dan Work, aku dapat menggunakan index CONTEXT. Untuk meng-index teks yang tidak terlalu banyak dan dapat menyertakan kolom lain dalam pencarian, aku menggunakan index CTXCAT. Index CTXRULE dibangun berdasarkan query dari tabel lain. Index CTXXPATH dipakai untuk kolom bertipe XMLType yang menampung data XML.

Sebagai latihan pertama, aku akan menyimpan beberapa Microsoft Word (DOC) ke dalam sebuah folder. Index berjenis CONTEXT mendukung pencarian teks terhadap file yang disimpan di luar tabel seperti ini. Aku mulai dengan membuat data storage preference yang berisi lokasi penyimpan file DOC:


BEGIN
  ctx_ddl.
    create_preference(
      'storage_doc_attachment', 
      'FILE_DATASTORE');
  ctx_ddl.
    set_attribute(
      'storage_doc_attachment', 
      'PATH', 
      'C:\DOC');
END;
/

Karena format dokumen yang aku pakai adalah format Microsoft Word (DOC), maka aku memakai filtering INSO_FILTER yang juga mendukung PDF dan MacWriteII. Dengan demikian, perintah untuk membuat index CONTEXT dalam latihan-ku ini akan menjadi:


CREATE INDEX IDX_DOC_ATTACHMENT ON TBL_ATTACHMENT(ATTACHMENT) INDEXTYPE IS CTXSYS.CONTEXT
PARAMETERS ('DATASTORE storage_doc_attachment FILTER ctxsys.inso_filter');

Lalu, aku menempatkan beberapa file Microsoft Word (DOC) ke folder C:\DOC, kemudian menambahkan record baru ke tabel serta me-rebuild index:


INSERT INTO TBL_ATTACHMENT 
  VALUES (1, 'document1.doc');
INSERT INTO TBL_ATTACHMENT 
  VALUES (2, 'document2.doc');
INSERT INTO TBL_ATTACHMENT 
  VALUES (3, 'document3.doc');
ALTER INDEX IDX_DOC_ATTACHMENT 
  REBUILD;

Sekarang, aku siap untuk menguji Oracle Text, misalnya dengan query berikut:


SELECT * FROM TBL_ATTACHMENT WHERE CONTAINS(attachment, 'exam') > 0;

Salah satu kelebihan Oracle Text ketimbang query dengan operator LIKE adalah kemampuannya mengenali kata. Query di atas hanya akan mencari dokumen Word yang mengandung kata “exam” saja, tidak termasuk “examination”.

Day 25: Oracle Workspace Manager

Learning In HomeOriginal Date: 6 Februari 2009

Workspace Manager merupakan fitur database Oracle yang cukup berguna bila dipakai dalam proses QA (Quality Assurance). Workspace Manager memungkinkan versioning pada sebuah tabel, layaknya memakai versioning di CVS. Untuk menggunakan Workspace Manager, aku memakai API yang tersedia di package DBMS_WM. Aku akan memulai dengan mengaktifkan versioning pada sebuah tabel:


EXECUTE DBMS_WM.ENABLEVERSIONING('TBL_BARANG,TBL_KATEGORI', 'VIEW_WO_OVERWRITE');

Perintah di atas akan mengaktifkan versioning pada tabel TBL_BARANG dan TBL_KATEGORI, dimana kedua tabel tersebut saling berhubungan. Selain itu, akan terbentuk view dengan nama TBL_BARANG_HIST dan TBL_KATEGORI_HIST yang menampung history perubahan atas kedua tabel tersebut. Lalu, aku membuat workspace baru:


EXECUTE DBMS_WM.CREATEWORKSPACE('SAMPLE_SCENARIO');
EXECUTE DBMS_WM.CREATEWORKSPACE('SAMPLE_SCENARIO_B');

Kemudian, aku berpindah ke workspace SAMPLE_SCENARIO:


EXECUTE DBMS_WM.GOTOWORKSPACE('SAMPLE_SCENARIO');

Sekarang, pada workspace ini, aku dapat melakukan berbagai perubahan pada tabel TBL_BARANG dan TBL_KATEGORI. Setelah puas, aku berpindah ke workspace yang lain:


EXECUTE DBMS_WM.GOTOWORKSPACE('SAMPLE_SCENARIO_B');

Pada workspace SAMPLE_SCENARIO_B yang berbeda ini, jika aku men-select isi table, aku tidak akan menemukan perubahan record lama dan record yang baru di-insert di workspace SAMPLE_SCENARIO_B. Aku kembali bebas melakukan modifikasi data di workspace ini dengan memberikan perintah DML.

Setelah itu, aku kembali ke parent workspace yang paling utama, yang namanya berupa LIVE (huruf besar):


EXECUTE DBMS_WM.GOTOWORKSPACE('LIVE');

Jika aku men-select TBL_BARANG sekarang, isinya persis seperti semula saat sebelum aku melakukan modifikasi di kedua workspace. Sekarang, aku dapat berpindah-pindah antar workspace dan mendapatkan versi yang berbeda-beda dari sebuah tabel yang sama. Setelah itu, aku dapat memutuskan untuk menghapus workspace yang mana, dan men-merge atau melakukan rollback pada workspace tertentu, seperti:


EXECUTE DBMS_WM.
  GOTOWORKSPACE('LIVE');
EXECUTE DBMS_WM.
  REMOVEWORKSPACE('SAMPLE_SCENARIO_B');
EXECUTE DBMS_WM.
  MERGEWORKSPACE('SAMPLE_SCENARIO');
SELECT * FROM TBL_BARANG;

Perintah di atas akan menghapus workspace SAMPLE_SCENARIO_B dan men-merge isi workspace SAMPLE_SCENARIO dengan isi workspace LIVE. Aku juga bisa men-rollback isi tabel dan men-nonaktif-kan versioning dengan perintah:


EXECUTE DBMS_WM.ROLLBACKTABLE('SAMPLE_SCENARIO', 'TBL_BARANG');


EXECUTE DBMS_WM.DISABLEVERSIONING('TBL_BARANG,TBL_KATEGORI');

Selama menggunakan workspace manager, aku dapat melihat semua ini perubahan TBL_BARANG melalui view TBL_BARANG_HIST.

Day 24: Oracle Expression Filter

Learning In HomeOriginal Date: 5 Februari 2009

Oracle Expression Filter adalah salah satu fitur database Oracle yang memungkinkan pengerjaan ekspresi yang disimpan sebagai data di dalam tabel. Ekspresi ini bernilai antara TRUE dan FALSE. Kolom yang menampung ekspresi memiliki tipe VARCHAR2. Sebuah tabel dapat mengandung lebih dari satu kolom ekspresi. Sebagai contoh, aku membuat tabel berikut:


CREATE TABLE TBL_USER (
  NAMA VARCHAR2(100),
  PILIHAN VARCHAR2(100)
);

Aku menginginkan kolom PILIHAN berisi nilai ekspresi yang akan dievaluasi oleh Oracle Expression Filter. Untuk itu, aku harus mulai dengan membuat attribute set dan mengisi atribut-atributnya:


BEGIN

dbms_expfil.
create_attribute_set(
 attr_set => 'PilihanUser');

dbms_expfil.
add_elementary_attribute(
attr_set => 'PilihanUser', 
attr_name=> 'NamaBarang', 
attr_type => 'VARCHAR2(100)');

dbms_expfil.
add_elementary_attribute(
attr_set => 'PilihanUser', 
attr_name=> 'Harga', 
attr_type => 'NUMBER(18)');

dbms_expfil.
add_elementary_attribute(
attr_set => 'PilihanUser', 
attr_name=> 'Kategori', 
attr_type => 'NUMBER(5)');  

END;
/

Kode di atas akan membuat sebuah attribute set dengan nama PilihanUser. Di dalam attribute set tersebut, terdapat attribute-attribute seperti NamaBarang, Harga, dan Kategori. Setelah itu, aku akan men-assign attribute set tersebut ke kolom PILIHAN di tabel TBL_USER dengan perintah seperti berikut ini:


BEGIN

dbms_expfil.
assign_attribute_set(
attr_set => 'PilihanUser', 
expr_tab => 'TBL_USER', 
expr_col => 'PILIHAN');

END;
/

Lalu, aku memasukkan data latihan ke TBL_USER seperti:


INSERT INTO TBL_USER VALUES 
('Solid Snake', 
 'Kategori = 10 AND Harga < 4000000');

INSERT INTO TBL_USER VALUES 
('Liquid Snake', 
 'Harga > 2000000');

INSERT INTO TBL_USER VALUES 
('Big Boss', 
 'NamaBarang = ''Calibre GeForce 8800 Ultra''');

Dan aku siap memakai Oracle Expression Filter, seperti pada contoh berikut:


SELECT * FROM TBL_USER WHERE EVALUATE(PILIHAN, 'Harga=>3000000,Kategori=>1,NamaBarang=>''TEST''')=1;

Query di atas akan mengembalikan user Liquid Snake.

Untuk melihat daftar attribute yang ada, aku dapat memeriksa isi view USER_EXPFIL_ATTRIBUTES seperti:


SELECT * FROM USER_EXPFIL_ATTRIBUTES;

Day 23: Menyimpan XML di XML DB Repository Data

Learning In HomeOriginal Date: 4 Februari 2009

Jika sebelumnya aku menyimpan XML di dalam tabel dengan menggunakan tipe data XMLType, maka hari ini aku akan mencoba menyimpan XML ke dalam repository XML DB (tanpa melalui tabel database). Di dalam repository tersebut, aku mengakses data dalam struktur tree folder seolah-olah mengakses file yang tersimpan di harddisk. Sebenarnya data di repository juga disimpan sebagai kumpulan tabel dan index di dalam schema database Oracle. Salah satu view yang berguna untuk mengetahui informasi repository melalui SQL adalah RESOURCE_VIEW dan PATH_VIEW.

Aku dapat mengakses repository melalui protokol FTP, HTTP, dan WebDav. Pengaturan untuk protokol-protokol tersebut terdapat di xdbconfig.xml yang terletak di root. Untuk melihat isi file xdbconfig.xml pada node yang aku inginkan, aku dapat memberikan query SQL berikut:


SELECT xmltype(extract(res, '/Resource/Contents/*').getClobVal()).extract('/xdbconfig/sysconfig/protocolconfig') FROM RESOURCE_VIEW
WHERE ANY_PATH = '/xdbconfig.xml';

Pengaturan untuk protokol FTP dapat dilihat di /xdbconfig/sysconfig/protocolconfig/ftpconfig. Secara default, ftp port yang dipakai adalah 2100 . Pengaturan untuk protokol HTTP dapat dilihat di /xdbconfig/sysconfig/protocolconfig/httpconfig. Secara default, http port yang dipakai adalah 8080.

Untuk melihat isi repository melalui Internet Exploper, aku tinggal mengetikkan link berikut:


http://localhost:8080

kemudian mengisi username dan password sesuai dengan user database Oracle. Untuk melakukan modifikasi terhadap repository, aku dapat menggunakan WebDAV, yaitu dengan men-klik Add Network Place di My Network Places, kemudian mengisi lokasi dengan http://localhost:8080. Setelah itu, aku bisa men-browse repository dengan Windows Explorer, serta melakukan operasi copy paste, layaknya file di harddisk.

Day 22: Memakai Tipe Data XMLType Melalui JDBC

Learning In HomeOriginal Date: 3 Februari 2009

Hari ini aku akan melakukan latihan bagaimana membaca tipe data XMLType dari program Java. Untuk itu, aku membutuhkan class oracle.xdb.XMLType yang terletak di %ORACLE_HOME%\rdbms\jlib\xdb.jar. Setelah itu, aku dapat memberikan kode untuk mengambil nilai XMLType, seperti berikut:


rs.next();
XMLType dataXML = 
  (XMLType) rs.getObject(1);
System.out.println(
  dataXML.getStringVal());

Untuk menambahkan record baru yang berisi data XML dalam bentuk XMLType, aku dapat menggunakan kode program seperti berikut ini:


OraclePreparedStatement ps = 
  (OraclePreparedStatement) 
  cn.prepareStatement(
  "INSERT INTO TBL_XML 
   (DATA_ID, DATA_XML) 
   VALUES (?,?)");
ps.setString(1, "ACC99");
XMLType xmlType = new XMLType(cn, 
  "<account id='acc99'><debet>

   <tanggal>01/02/2009</tanggal>
   <jumlah>1000</jumlah></debet>
   </account>");
ps.setObject(2, xmlType);
ps.execute();

Untuk men-update data XML, misalnya aku ingin mengubah record yang dibuat di atas dengan nilai elemen jumlah yang semula bernilai 1000 menjadi 2000, aku dapat menggunakan cara yang sama, misalnya seperti berikut:


XMLType dataXML = 
 (XMLType) rs.getObject(1);
Document doc = dataXML.getDOM();
 Element eAccount = 
doc.getDocumentElement();
 Element eDebet = (Element) 
eAccount.getFirstChild();
 Element eJumlah = (Element) 
eDebet.getLastChild();		
eJumlah.getFirstChild().
 setNodeValue("2000");
			
dataXML = new XMLType(cn, doc);
OraclePreparedStatement ps = 
 (OraclePreparedStatement) 
 cn.prepareStatement("UPDATE TBL_XML 
  SET DATA_XML = ? 
  WHERE DATA_ID = 'ACC99'");
ps.setObject(1, dataXML);
ps.execute();
rs.close();
ps.close();

Day 21: Membuat XML dari Data Relational

Learning In HomeOriginal Date: 2 Februari 2009

Untuk menghasilkan data XML dari data relational, aku menggunakan fungsi xmlElement(), xmlAttributes(), xmlForest(), dan xmlAgg().

Sebagai contoh, query berikut:


SELECT xmlElement("karyawan", xmlElement("nama",null,ENAME)) FROM EMP;

akan menghasilkan baris yang seperti berikut ini:


<karyawan><nama>scott</nama></karyawan>

Cara lain untuk mengubah sebuah tabel menjadi data XML adalah dengan menggunakan dbUriType(), seperti pada contoh berikut:


SELECT dbUriType('/SCOTT/EMP').getXML() FROM DUAL;

yang akan menghasilkan XML seperti pada contoh berikut:

<?xml version="1.0"?>
<EMP>
  <ROW>
     <EMPNO>7782</EMPNO>
     <ENAME>CLARK</ENAME>

     ...
  </ROW>
  ...
</EMP>