You are on page 1of 290

Chupter ll: lntroducng lL/SQL lrogrummng

371
1he exumpe trgger you' see n ths secton lres belore un updute ol the price coumn n
the products tube, therelore, l' nume the trgger before_product_price_update. Aso,
becuuse l wunt to use the price coumn vuues belore und ulter un UPDATE stutement modles
the price coumn's vuue, l must use u row-eve trgger. lnuy, l wunt to uudt u prce chunge
when the new prce s owered by more thun 25 percent ol the od prce, therelore, l' need to
specly u trgger condton to compure the new prce wth the od prce. 1he loowng stutement
creutes the before_product_price_update trgger:
CREATE TRIGGER before_product_price_update
BEFORE UPDATE OF price
ON products
FOR EACH ROW WHEN (new.price < old.price * 0.75)
BEGIN
dbms_output.put_line('product_id = ' || :old.product_id);
dbms_output.put_line('Old price = ' || :old.price);
dbms_output.put_line('New price = ' || :new.price);
dbms_output.put_line('The price reduction is more than 25%');
-- insert row into the product_price_audit table
INSERT INTO product_price_audit (
product_id, old_price, new_price
) VALUES (
:old.product_id, :old.price, :new.price
);
END before_product_price_update;
/
1here ure lve thngs you shoud notce ubout ths stutement:
BEFORE UPDATE OF price meuns the trgger lres belore un updute ol the price
coumn.
FOR EACH ROW meuns ths us u row-eve trgger, thut s, the trgger code contuned
wthn the BEGIN und END keywords runs once lor euch row modled by the updute.
1he trgger condton s (new.price < old.price * 0.75), whch meuns the
trgger lres ony when the new prce s ess thun 75 percent ol the od prce (thut s,
when the prce s reduced by more thun 25 percent).
1he new und od coumn vuues ure uccessed usng the :old und :new uuses n the trgger.
1he trgger code dspuys the product_id, the od und new prices, und u messuge
stutng thut the prce reducton s more thun 25 percent. 1he code then udds u row to the
product_price_audit tube contunng the product_id und the od und new prces.
firing a Triggcr
1o see the output lrom the trgger, you need to run the SET SERVEROUTPUT ON commund:
SET SERVEROUTPUT ON
1o lre the before_product_price_update trgger, you must reduce u product's prce by
more thun 25 percent. Co uheud und perlorm the loowng UPDATE stutement to reduce the prce
372
Cruce Dutubuse llg SQL
ol products r5 und rl0 by 30 percent (ths s ucheved by mutpyng the price coumn by .7).
1he loowng UPDATE stutement cuuses the before_product_price_update trgger to lre:
UPDATE products
SET price = price * .7
WHERE product_id IN (5, 10);
product_id = 10
Old price = 15.99
New price = 11.19
The price reduction is more than 25%
product_id = 5
Old price = 49.99
New price = 34.99
The price reduction is more than 25%
2 rows updated.
As you cun see, the trgger lred lor products rl0 und r5. You cun see thut the trgger dd
ndeed udd the two requred rows contunng the product_ids, uong wth the od und new
prces, to the product_price_audit tube usng the loowng query:
SELECT *
FROM product_price_audit
ORDER BY product_id;
PRODUCT_ID OLD_PRICE NEW_PRICE
---------- ---------- ----------
5 49.99 34.99
10 15.99 11.19
Gctting lnfurmatiun un Triggcrs
You cun get nlormuton on your trggers lrom the user_triggers vew. 1ube ll-3 descrbes
some ol the coumns n user_triggers.
CuIumn Typc Dcscriptiun
TRIGGER_NAME VARCHAR2(30)
Nume ol the trgger.
TRIGGER_TYPE VARCHAR2(16)
1ype ol the trgger.
TRIGGERING_EVENT VARCHAR2(227)
Lvent thut cuuses the trgger to lre.
TABLE_OWNER VARCHAR2(30)
Lser who owns the tube thut the trgger
relerences.
BASE_OBJECT_TYPE VARCHAR2(16)
1ype ol the obect relerenced by the trgger.
TABLE_NAME VARCHAR2(30)
Nume ol the tube relerenced by the trgger.
COLUMN_NAME VARCHAR2(4000)
Nume ol the coumn relerenced by the
trgger.
TABlf 11-3 Somc Coumn n |hc user_triggers Vcv
Chupter ll: lntroducng lL/SQL lrogrummng
373
NOTf
You can gc| n|orma|on on a |hc |rggcr ,ou havc accc |o ung
all_triggers.
1he loowng exumpe retreves the detus ol the before_product_price_update
trgger lrom user_triggers (the output s prnted pretty lor curty):
SELECT trigger_name, trigger_type, triggering_event, table_owner
base_object_type, table_name, referencing_names, when_clause, status,
description, action_type, trigger_body
FROM user_triggers
WHERE trigger_name = 'BEFORE_PRODUCT_PRICE_UPDATE';
TRIGGER_NAME TRIGGER_TYPE
------------------------------ ----------------
BEFORE_PRODUCT_PRICE_UPDATE BEFORE EACH ROW
TRIGGERING_EVENT
----------------
UPDATE
TABLE_OWNER BASE_OBJECT_TYPE TABLE_NAME
------------------------------ ---------------- -----------
STORE TABLE PRODUCTS
REFERENCING_NAMES
-----------------------------------------------------------
REFERENCING NEW AS NEW OLD AS OLD
WHEN_CLAUSE
-----------------------------------------------------------
new.price < old.price * 0.75
CuIumn Typc Dcscriptiun
REFERENCING_NAMES VARCHAR2(128)
Nume ol the od und new uuses.
WHEN_CLAUSE VARCHAR2(4000)
1rgger condton thut mts when the
trgger runs ts code.
STATUS VARCHAR2(8)
\hether the trgger s enubed or
dsubed (ENABLED or DISABLED).
DESCRIPTION VARCHAR2(4000)
Descrpton ol the trgger.
ACTION_TYPE VARCHAR2(11)
Acton type ol the trgger (CALL or
PL/SQL).
TRIGGER_BODY LONG
Code contuned n the trgger body. (1he
LONG type uows storuge ol urge umounts
ol text. You' eurn ubout the LONG type n
Chupter l4.)
TABlf 11-3 Somc Coumn n |hc user_triggers Vcv (contnued)
374
Cruce Dutubuse llg SQL
STATUS
--------
ENABLED
DESCRIPTION
-----------------------------------------------------------
before_product_price_update
BEFORE UPDATE OF
price
ON
products
FOR EACH ROW
ACTION_TYPE
-----------
PL/SQL
TRIGGER_BODY
-----------------------------------------------------------
BEGIN
dbms_output.put_line('product_id = ' || :old.product_id);
dbms_output...
NOTf
You can cc a |hc codc |or |hc |rggcr ung |hc S*u SET LONG
command, |or cxampc, SET LONG 1000.
DisabIing and fnabIing a Triggcr
You cun stop u trgger lrom lrng by dsubng t by usng the ALTER TRIGGER stutement. 1he
loowng exumpe dsubes the before_product_price_update trgger:
ALTER TRIGGER before_product_price_update DISABLE;
1he next exumpe enubes the before_product_price_update trgger:
ALTER TRIGGER before_product_price_update ENABLE;
Drupping a Triggcr
You drop u trgger usng DROP TRIGGER. 1he loowng exumpe drops the before_product_
price_update trgger:
DROP TRIGGER before_product_price_update;
Ncw OracIc Databasc 11 Pl/SQl fcaturcs
ln ths secton, you' see some ol the new lL/SQL leutures ntroduced n Cruce Dutubuse llg.
Speclcuy, the loowng w be dscussed:
1he SIMPLE_INTEGER type
Support lor sequences n lL/SQL
lL/SQL nutve muchne code generuton
Chupter ll: lntroducng lL/SQL lrogrummng
37S
SlMPlf_lNTfGfR Typc
1he SIMPLE_INTEGER type s u subtype ol BINARY_INTEGER, the SIMPLE_INTEGER cun store
the sume runge us BINARY_INTEGER, except SIMPLE_INTEGER cunnot store u NULL vuue.
1he runge ol vuues SIMPLE_INTEGER cun store s 2
3l
(2,l47,483,648) to 2
3l
(2,l47,483,648).
Arthmetc overlow s truncuted when usng SIMPLE_INTEGER vuues, therelore, cucuutons
don't ruse un error when overlow occurs. ecuuse overlow errors ure gnored, the vuues stored
n u SIMPLE_INTEGER cun wrup lrom postve to negutve und lrom negutve to postve, us, lor
exumpe:
2
30
+ 2
30
= 0x40000000 + 0x40000000 = 0x80000000 = 2
3l
2
3l
+ 2
3l
= 0x80000000 + 0x80000000 = 0x00000000 = 0
ln the lrst exumpe, two postve vuues ure udded, und u negutve totu s produced. ln the
second exumpe, two negutve vuues ure udded, und zero s produced.
ecuuse overlow s gnored und truncuted when usng SIMPLE_INTEGER vuues n cucuutons,
SIMPLE_INTEGER ollers much better perlormunce thun BINARY_INTEGER when the DA
conlgures the dutubuse to compe lL/SQL to nutve muchne code. ecuuse ol ths benelt, you
shoud use SIMPLE_INTEGER n your lL/SQL code when you don't need to store u NULL und
you don't cure ubout overlow truncuton occurrng n your cucuutons, otherwse, you shoud
use BINARY_INTEGER.
1he loowng get_area() procedure shows the use ol the SIMPLE_INTEGER type, get_
area() cucuutes und dspuys the ureu ol u rectunge:
CREATE PROCEDURE get_area
AS
v_width SIMPLE_INTEGER := 10;
v_height SIMPLE_INTEGER := 2;
v_area SIMPLE_INTEGER := v_width * v_height;
BEGIN
DBMS_OUTPUT.PUT_LINE('v_area = ' || v_area);
END get_area;
/
NOTf
You' |nd |h cxampc, and |hc o|hcr cxampc n |h cc|on, n a
crp| namcd plsql_11g_examples.sql n |hc SQL drcc|or,. You
ma, run |h crp| | ,ou arc ung Cracc Da|abac 11g.
1he loowng exumpe shows the executon ol get_area():
SET SERVEROUTPUT ON
CALL get_area();
v_area = 20
As expected, the cucuuted ureu s 20.
Scqucnccs in Pl/SQl
ln the prevous chupter you suw how to creute und use sequences ol numbers n SQL. ln Cruce
Dutubuse llg, you cun uso use sequences n lL/SQL code.
As u remnder, u sequence generutes u seres ol numbers. \hen you creute u sequence n
SQL, you cun specly ts ntu vuue und un ncrement lor the seres ol subsequent numbers.

Cruce Dutubuse ll SQL
You use the currval pseudo coumn to get the current vuue n the sequence und nextval to
generute the next number. elore you uccess currval, you must lrst use nextval to generute
un ntu number.
1he loowng stutement creutes u tube numed new_products, ths tube w be used shorty:
CREATE TABLE new_products (
product_id INTEGER CONSTRAINT new_products_pk PRIMARY KEY,
name VARCHAR2(30) NOT NULL,
price NUMBER(5, 2)
);
1he next stutement creutes u sequence numed s_product_id:
CREATE SEQUENCE s_product_id;
1he loowng stutement creutes u procedure numed add_new_products, whch uses s_
product_id to set the product_id coumn n u row udded to the new_products tube,
notce the use ol the nextval und currval pseudo coumns n the lL/SQL code (ths s new
lor Cruce Dutubuse ll):
CREATE PROCEDURE add_new_products
AS
v_product_id BINARY_INTEGER;
BEGIN
-- use nextval to generate the initial sequence number
v_product_id := s_product_id.nextval;
DBMS_OUTPUT.PUT_LINE('v_product_id = ' || v_product_id);
-- add a row to new_products
INSERT INTO new_products
VALUES (v_product_id, 'Plasma Physics book', 49.95);
DBMS_OUTPUT.PUT_LINE('s_product_id.currval = ' || s_product_id.currval);
-- use nextval to generate the next sequence number
v_product_id := s_product_id.nextval;
DBMS_OUTPUT.PUT_LINE('v_product_id = ' || v_product_id);
-- add another row to new_products
INSERT INTO new_products
VALUES (v_product_id, 'Quantum Physics book', 69.95);
DBMS_OUTPUT.PUT_LINE('s_product_id.currval = ' || s_product_id.currval);
END add_new_products;
/
1he loowng exumpe runs add_new_products() und shows the contents ol the new_
products tube:
SET SERVEROUTPUT ON
CALL add_new_products();
v_product_id = 1
Chupter ll: lntroducng lL/SQL lrogrummng
377
s_product_id.currval = 1
v_product_id = 2
s_product_id.currval = 2
SELECT * FROM new_products;
PRODUCT_ID NAME PRICE
---------- ------------------------------ ----------
1 Plasma Physics book 49.95
2 Quantum Physics book 69.95
As expected, two rows were udded to the tube.
Pl/SQl Nativc Machinc Cudc Gcncratiun
y deluut, euch lL/SQL progrum unt s comped nto ntermedute lorm, muchne-reudube code.
1hs muchne-reudube code s stored n the dutubuse und nterpreted every tme the code s run.
\th lL/SQL nutve computon, the lL/SQL s turned nto nutve code und stored n shured
brures. Nutve code runs much luster thun ntermedute code becuuse nutve code doesn't huve
to be nterpreted belore t runs.
ln certun versons ol the dutubuse pror to Cruce Dutubuse llg, you cun compe lL/SQL
code to C code, und then compe the C code nto muchne code, ths s u very uborous und
probemutc process. ln Cruce Dutubuse llg, the lL/SQL comper cun generute nutve muchne
code drecty. Settng up the dutubuse to generute nutve muchne code shoud be done ony by un
experenced DA (us such, ts coveruge s beyond the scope ol ths book). You cun reud u ubout
lL/SQL nutve muchne code generuton n the /S Lcr' Cudc and Rc|crcncc munuu lrom
Cruce Corporuton.
Summary
ln ths chupter, you eurned the loowng:
lL/SQL progrums ure dvded up nto bocks contunng lL/SQL und SQL stutements.
A oop, such us u WHILE or FOR oop, runs stutements mutpe tmes.
A cursor uows lL/SQL to reud the rows returned by u query.
Lxceptons ure used to hunde run-tme errors thut occur n your lL/SQL code.
A procedure contuns u group ol stutements. lrocedures uow you to centruze your
busness ogc n the dutubuse und muy be run by uny progrum thut uccesses the dutubuse.
A luncton s smur to u procedure except thut u luncton must return u vuue.
You cun group procedures und lunctons together nto puckuges, whch encupsuute
reuted lunctonuty nto one sel-contuned unt.
A trgger s u procedure thut s run uutomutcuy by the dutubuse when u speclc INSERT,
UPDATE, or DELETE stutement s run. 1rggers ure uselu lor dong thngs ke udvunced
uudtng ol chunges mude to coumn vuues n u tube.
ln the next chupter, you' eurn ubout dutubuse obects.
This page intentionally left blank
\IAI1II
1z
Dutubuse Cbects
379
380
Cruce Dutubuse llg SQL
n ths chupter, you w do the loowng:
Leurn ubout obects n the dutubuse
Leurn how to creute obect types contunng uttrbutes und methods
Lse obect types to delne coumn obects und obect tubes
Creute und munpuute obects n SQL und lL/SQL
Leurn how u type muy nhert lrom unother type und creute herurches ol types
Delne your own constructors to set the uttrbutes ol un obect
See how to overrde u method n one type wth u method lrom unother type
lntruducing Objccts
Cbect-orented progrummng unguuges such us }uvu, C++, und Cr uow you to delne cusses,
und these cusses uct us temputes lrom whch you cun creute obects. Cusses delne uttrbutes
und methods, uttrbutes ure used to store un obect's stute, und methods ure used to mode un
obect's behuvors.
\th the reeuse ol Cruce Dutubuse 8, obects becume uvuube wthn the dutubuse, und
obect leutures huve been mproved upon n subsequent product reeuses. 1he uvuubty ol obects
n the dutubuse wus u muor breukthrough becuuse they enube you to delne your own cusses,
known us ob]cc| |,pc, n the dutubuse. Lke cusses n }uvu und Cr, dutubuse obect types cun
contun uttrbutes und methods. Cbect types ure uso sometmes known us user-delned types.
A smpe exumpe ol un obect type woud be u type thut represents u product. 1hs obect type
coud contun uttrbutes lor the product's nume, descrpton, prce, und, n the cuse ol u product
thut s pershube, the number ol duys the product cun st on the shel belore t must be thrown
uwuy. 1hs product obect type coud uso contun u method thut returns the se-by dute ol the
product, bused on the shel le ol the product und the current dute. Another exumpe ol un obect
type s one thut represents u person, ths obect type coud store uttrbutes lor the person's lrst nume,
ust nume, dute ol brth, und uddress, the person's uddress coud tsel be represented by un obect
type, und t coud store thngs ke the street, cty, stute, und zp code. ln ths chupter you' see
exumpes ol obect types thut represent u product, person, und uddress. You' uso see how to
creute tubes lrom those obect types, popuute those tubes wth uctuu obects, und munpuute
those obects n SQL und lL/SQL.
l've provded un SQL*lus scrpt numed object_schema.sql n the SQL drectory, whch
creutes u user numed object_user wth u pussword ol object_password. 1hs scrpt uso
creutes the types und tubes, perlorms the vurous INSERT stutements, und creutes the lL/SQL
code shown n the lrst purt ol ths chupter. You must run ths scrpt whe ogged n us u user wth
the requred prveges to creute u new user wth the CONNECT, RESOURCE, und CREATE PUBLIC
SYNONYM prveges, l og n us the system user on my dutubuse to run the scrpts. Alter the scrpt
competes, you w be ogged n us object_user.

Chupter l2: Dutubuse Cbects


381
Crcating Objcct Typcs
You creute un obect type usng the CREATE TYPE stutement. 1he loowng exumpe uses the
CREATE TYPE stutement to creute un obect type numed t_address. 1hs obect type s used
to represent un uddress und contuns lour uttrbutes numed street, city, state, und zip:
CREATE TYPE t_address AS OBJECT (
street VARCHAR2(15),
city VARCHAR2(15),
state CHAR(2),
zip VARCHAR2(5)
);
/
1he exumpe shows thut euch uttrbute s delned usng u dutubuse type. lor exumpe,
street s delned us VARCHAR2(15). As you' see shorty, the type ol un uttrbute cun tsel
be un obect type.
1he next exumpe creutes un obect type numed t_person, notce thut t_person hus un
uttrbute numed address, whch s ol type t_address:
CREATE TYPE t_person AS OBJECT (
id INTEGER,
first_name VARCHAR2(10),
last_name VARCHAR2(10),
dob DATE,
phone VARCHAR2(12),
address t_address
);
/
1he loowng exumpe creutes un obect type numed t_product thut w be used to
represent products, notce thut ths type decures u luncton numed get_sell_by_date()
usng the MEMBER FUNCTION cuuse:
CREATE TYPE t_product AS OBJECT (
id INTEGER,
name VARCHAR2(15),
description VARCHAR2(22),
price NUMBER(5, 2),
days_valid INTEGER,
-- get_sell_by_date() returns the date by which the
-- product must be sold
MEMBER FUNCTION get_sell_by_date RETURN DATE
);
/
ecuuse t_product contuns u method decuruton, u lor t_product must uso be
creuted. 1he body contuns the uctuu code lor the method, und the body s creuted usng the
CREATE TYPE BODY stutement. 1he loowng exumpe creutes the body lor t_product,
notce the body contuns the code lor the get_sell_by_date() luncton.
382
Cruce Dutubuse ll SQL
CREATE TYPE BODY t_product AS
-- get_sell_by_date() returns the date by which the
-- product must be sold
MEMBER FUNCTION get_sell_by_date RETURN DATE IS
v_sell_by_date DATE;
BEGIN
-- calculate the sell by date by adding the days_valid attribute
-- to the current date (SYSDATE)
SELECT days_valid + SYSDATE
INTO v_sell_by_date
FROM dual;
-- return the sell by date
RETURN v_sell_by_date;
END;
END;
/
As you cun see, get_sell_by_date() cucuutes und returns the dute by whch the
product must be sod, t does ths by uddng the days_valid uttrbute to the current dute
returned by the but-n dutubuse SYSDATE() luncton.
You cun uso creute u pubc synonym lor u type, whch enubes u users to see the type und
use t to delne coumns n ther own tubes. 1he loowng exumpe creutes u pubc synonym
numed t_pub_product lor t_product:
CREATE PUBLIC SYNONYM t_pub_product FOR t_product;
Using DfSCRlBf tu Gct lnfurmatiun
un Objcct Typcs
You cun use the DESCRIBE commund to get nlormuton on un obect type. 1he loowng
exumpes show the t_address, t_person, und t_product types:
DESCRIBE t_address
Name Null? Type
----------------------------------------- -------- ------------
STREET VARCHAR2(15)
CITY VARCHAR2(15)
STATE CHAR(2)
ZIP VARCHAR2(5)
DESCRIBE t_person
Name Null? Type
----------------------------------------- -------- ------------
ID NUMBER(38)
FIRST_NAME VARCHAR2(10)
LAST_NAME VARCHAR2(10)
DOB DATE
PHONE VARCHAR2(12)
ADDRESS T_ADDRESS
Chupter l2: Dutubuse Cbects
383
DESCRIBE t_product
Name Null? Type
----------------------------------------- -------- ------------
ID NUMBER(38)
NAME VARCHAR2(10)
DESCRIPTION VARCHAR2(22)
PRICE NUMBER(5,2)
DAYS_VALID INTEGER
METHOD
------
MEMBER FUNCTION GET_SELL_BY_DATE RETURNS DATE
You cun set the depth to whch DESCRIBE w show nlormuton lor embedded types usng
SET DESCRIBE DEPTH. 1he loowng exumpe sets the depth to 2 und then descrbes t_person
ugun, notce thut the uttrbutes ol address ure dspuyed, whch s un embedded obect ol type
t_address:
SET DESCRIBE DEPTH 2
DESCRIBE t_person
Name Null? Type
----------------------------------------- -------- ------------
ID NUMBER(38)
FIRST_NAME VARCHAR2(10)
LAST_NAME VARCHAR2(10)
DOB DATE
PHONE VARCHAR2(12)
ADDRESS T_ADDRESS
STREET VARCHAR2(15)
CITY VARCHAR2(15)
STATE CHAR(2)
ZIP VARCHAR2(5)
Using Objcct Typcs in Databasc TabIcs
Now thut you've seen how to creute obect types, et's ook ut how you use these types n dutubuse
tubes. You cun use un obect type to delne un ndvduu coumn n u tube, und the obects
subsequenty stored n thut coumn ure known us coumn ob]cc|. You cun uso use un obect type to
delne un entre row n u tube, the tube s then known us un ob]cc| |abc. lnuy, you cun use un ob]cc|
rc|crcncc to uccess un ndvduu row n un obect tube, un obect relerence s smur to u ponter n
C++. You' see exumpes ol coumn obects, obect tubes, und obect relerences n ths secton.
CuIumn Objccts
1he loowng exumpe creutes u tube numed products thut contuns u coumn numed product
ol type t_product, the tube uso contuns u coumn numed quantity_in_stock, whch s
used to store the number ol those products currenty n stock:
CREATE TABLE products (
product t_product,
quantity_in_stock INTEGER
);

Cruce Dutubuse ll SQL
\hen uddng u row to ths tube, you must use u to suppy the uttrbute vuues lor
the new t_product obect, us u remnder, the t_product type wus creuted usng the loowng
stutement:
CREATE TYPE t_product AS OBJECT (
id INTEGER,
name VARCHAR2(10),
description VARCHAR2(22),
price NUMBER(5, 2),
days_valid INTEGER,
-- declare the get_sell_by_date() member function,
-- get_sell_by_date() returns the date by which the
-- product must be sold
MEMBER FUNCTION get_sell_by_date RETURN DATE
);
/
A constructor s u but-n method lor the obect type, und t hus the sume nume us the obect
type, the constructor uccepts purumeters thut ure used to set the uttrbutes ol the new obect. 1he
constructor lor the t_product type s numed t_product und uccepts lve purumeters, one
to set euch ol the uttrbutes, lor exumpe, t_product(1, pasta, 20 oz bag of pasta,
3.95, 10) creutes u new t_product obect und sets ts id to l, name to pasta, description
to 20 oz bag of pasta, price to 3.95, und days_valid to l0.
1he loowng INSERT stutements udd two rows to the products tube, notce the use
ol the t_product constructor to suppy the uttrbute vuues lor the product coumn
obects:
INSERT INTO products (
product,
quantity_in_stock
) VALUES (
t_product(1, 'pasta', '20 oz bag of pasta', 3.95, 10),
50
);
INSERT INTO products (
product,
quantity_in_stock
) VALUES (
t_product(2, 'sardines', '12 oz box of sardines', 2.99, 5),
25
);
1he loowng query retreves these rows lrom the products tube, notce thut the product
coumn obects' uttrbutes ure dspuyed wthn u constructor lor t_product:
SELECT *
FROM products;
Chupter l2: Dutubuse Cbects

PRODUCT(ID, NAME, DESCRIPTION, PRICE, DAYS_VALID)


----------------------------------------------------------
QUANTITY_IN_STOCK
-----------------
T_PRODUCT(1, 'pasta', '20 oz bag of pasta', 3.95, 10)
50
T_PRODUCT(2, 'sardines', '12 oz box of sardines', 2.99, 5)
25
You cun uso retreve un ndvduu coumn obect lrom u tube, to do ths, you must suppy u
tube uus through whch you seect the obect. 1he loowng query retreves product rl lrom the
products tube, notce the use ol the tube uus p lor the products tube, through whch the
product obect's id uttrbute s specled n the WHERE cuuse:
SELECT p.product
FROM products p
WHERE p.product.id = 1;
PRODUCT(ID, NAME, DESCRIPTION, PRICE, DAYS_VALID)
-----------------------------------------------------
T_PRODUCT(1, 'pasta', '20 oz bag of pasta', 3.95, 10)
1he next query expcty ncudes the product obect's id, name, price, und days_
valid uttrbutes n the SELECT stutement, pus the quantity_in_stock:
SELECT p.product.id, p.product.name,
p.product.price, p.product.days_valid, p.quantity_in_stock
FROM products p
WHERE p.product.id = 1;
PRODUCT.ID PRODUCT.NA PRODUCT.PRICE PRODUCT.DAYS_VALID QUANTITY_IN_STOCK
---------- ---------- ------------- ------------------ -----------------
1 pasta 3.95 10 50
1he t_product obect type contuns u luncton numed get_sell_by_date(), whch
cucuutes und returns the dute by whch the product must be sod. 1he luncton does ths by
uddng the days_valid uttrbute to the current dute, whch s obtuned lrom the dutubuse usng
the SYSDATE() luncton. You cun cu the get_sell_by_date() luncton usng u tube uus,
us shown n the loowng query thut uses the tube uus p lor the products tube:
SELECT p.product.get_sell_by_date()
FROM products p;
P.PRODUCT
---------
19-JUN-07
13-JUN-07
Cl course, l you run ths query your dutes w be dllerent, becuuse they ure cucuuted usng
SYSDATE(), whch returns the current dute und tme.
386
Cruce Dutubuse llg SQL
1he loowng UPDATE stutement modles the descrpton ol product rl, notce thut the tube
uus p s used ugun:
UPDATE products p
SET p.product.description = '30 oz bag of pasta'
WHERE p.product.id = 1;
1 row updated.
1he loowng DELETE stutement removes product r2:
DELETE FROM products p
WHERE p.product.id = 2;
1 row deleted.
ROLLBACK;
NOTf
| ,ou run |hcc UPDATE and DELETE |a|cmcn|, ma|c urc ,ou
cxccu|c |hc ROLLBACK o |ha| ,our cxampc da|a ma|chc |ha| hovn
n |hc rc| o| |h chap|cr.
Objcct TabIcs
You cun use un obect type to delne un entre tube, und such u tube s known us un obect tube.
1he loowng exumpe creutes un obect tube numed object_products, whch stores obects
ol type t_product, notce the use ol the OF keyword to dently the tube us un obect tube ol
type t_product:
CREATE TABLE object_products OF t_product;
\hen nsertng u row nto un obect tube, you cun choose whether to use u constructor to
suppy uttrbute vuues or to suppy the vuues n the sume wuy thut you woud suppy coumn
vuues n u reutonu tube. 1he loowng INSERT stutement udds u row to the object_
products tube usng the constructor lor t_product:
INSERT INTO object_products VALUES (
t_product(1, 'pasta', '20 oz bag of pasta', 3.95, 10)
);
1he next INSERT stutement omts the constructor lor t_product, notce thut the uttrbute
vuues lor t_product ure supped n the sume wuy thut coumns woud be n u reutonu tube:
INSERT INTO object_products (
id, name, description, price, days_valid
) VALUES (
2, 'sardines', '12 oz box of sardines', 2.99, 5
);
1he loowng query retreves these rows lrom the object_products tube:
SELECT *
FROM object_products;
Chupter l2: Dutubuse Cbects

ID NAME DESCRIPTION PRICE DAYS_VALID


---------- ---------- ---------------------- ---------- ----------
1 pasta 20 oz bag of pasta 3.95 10
2 sardines 12 oz box of sardines 2.99 5
You cun uso specly ndvduu obect uttrbutes n u query, lor exumpe, by dong ths:
SELECT id, name, price
FROM object_products op
WHERE id = 1;
ID NAME PRICE
---------- ---------- ----------
1 pasta 3.95
or ths:
SELECT op.id, op.name, op.price
FROM object_products op
WHERE op.id = 1;
ID NAME PRICE
---------- ---------- ----------
1 pasta 3.95
You cun use the but-n Cruce dutubuse VALUE() luncton to seect u row lrom un obect
tube. VALUE() treuts the row us un uctuu obect und returns the uttrbutes lor the obect wthn
u constructor lor the obect type. VALUE() uccepts u purumeter contunng u tube uus, us shown
n the loowng query:
SELECT VALUE(op)
FROM object_products op;
VALUE(OP)(ID, NAME, DESCRIPTION, PRICE, DAYS_VALID)
----------------------------------------------------------
T_PRODUCT(1, 'pasta', '20 oz bag of pasta', 3.95, 10)
T_PRODUCT(2, 'sardines', '12 oz box of sardines', 2.99, 5)
You cun uso udd un obect uttrbute ulter VALUE():
SELECT VALUE(op).id, VALUE(op).name, VALUE(op).price
FROM object_products op;
VALUE(OP).ID VALUE(OP). VALUE(OP).PRICE
------------ ---------- ---------------
1 pasta 3.95
2 sardines 2.99
1he loowng UPDATE stutement modles the descrpton ol product rl:
UPDATE object_products
SET description = '25 oz bag of pasta'
WHERE id = 1;
1 row updated.

Cruce Dutubuse ll SQL
1he loowng DELETE stutement removes product r2:
DELETE FROM object_products
WHERE id = 2;
1 row deleted.
ROLLBACK;
Let's tuke u ook ut u more compex obect tube. 1he loowng CREATE TABLE stutement
creutes un obect tube numed object_customers, whch stores obects ol type t_person:
CREATE TABLE object_customers OF t_person;
1he t_person type contuns un embedded t_address obect, t_person wus creuted
usng the loowng stutement:
CREATE TYPE t_person AS OBJECT (
id INTEGER,
first_name VARCHAR2(10),
last_name VARCHAR2(10),
dob DATE,
phone VARCHAR2(12),
address t_address
);
/
1he loowng INSERT stutements udd two rows nto object_customers. 1he lrst INSERT
uses constructors lor t_person und t_address, whe the second INSERT omts the t_person
constructor:
INSERT INTO object_customers VALUES (
t_person(1, 'John', 'Brown', '01-FEB-1955', '800-555-1211',
t_address('2 State Street', 'Beantown', 'MA', '12345')
)
);
INSERT INTO object_customers (
id, first_name, last_name, dob, phone,
address
) VALUES (
2, 'Cynthia', 'Green', '05-FEB-1968', '800-555-1212',
t_address('3 Free Street', 'Middle Town', 'CA', '12345')
);
1he loowng query retreves these rows lrom the object_customers tube, notce thut
the uttrbutes lor the embedded address coumn obect ure dspuyed wthn the t_address
constructor:
SELECT *
FROM object_customers;
Chupter l2: Dutubuse Cbects

ID FIRST_NAME LAST_NAME DOB PHONE


---------- ---------- ---------- --------- ------------
ADDRESS(STREET, CITY, STATE, ZIP)
--------------------------------------------------------
1 John Brown 01-FEB-55 800-555-1211
T_ADDRESS('2 State Street', 'Beantown', 'MA', '12345')
2 Cynthia Green 05-FEB-68 800-555-1212
T_ADDRESS('3 Free Street', 'Middle Town', 'CA', '12345')
1he next query retreves customer rl lrom object_customers, notce the use ol the tube
uus oc through whch the id uttrbute s specled n the WHERE cuuse:
SELECT *
FROM object_customers oc
WHERE oc.id = 1;
ID FIRST_NAME LAST_NAME DOB PHONE
---------- ---------- ---------- --------- ------------
ADDRESS(STREET, CITY, STATE, ZIP)
------------------------------------------------------
1 John Brown 01-FEB-55 800-555-1211
T_ADDRESS('2 State Street', 'Beantown', 'MA', '12345')
ln the loowng query, u customer s retreved bused on the state uttrbute ol the address
coumn obect:
SELECT *
FROM object_customers oc
WHERE oc.address.state = 'MA';
ID FIRST_NAME LAST_NAME DOB PHONE
---------- ---------- ---------- --------- ------------
ADDRESS(STREET, CITY, STATE, ZIP)
------------------------------------------------------
1 John Brown 01-FEB-55 800-555-1211
T_ADDRESS('2 State Street', 'Beantown', 'MA', '12345')
ln the next query, the id, first_name, und last_name uttrbutes ol customer rl ure
expcty ncuded n the SELECT stutement, uong wth the uttrbutes ol the embedded address
coumn obect:
SELECT oc.id, oc.first_name, oc.last_name,
oc.address.street, oc.address.city, oc.address.state, oc.address.zip
FROM object_customers oc
WHERE oc.id = 1;
ID FIRST_NAME LAST_NAME ADDRESS.STREET ADDRESS.CITY AD ADDRE
---------- ---------- ---------- --------------- --------------- -- -----
1 John Brown 2 State Street Beantown MA 12345
390
Cruce Dutubuse llg SQL
Objcct ldcntificrs and Objcct Rcfcrcnccs
Luch obect n un obect tube hus u unque ob]cc| dcn||cr (ClD), und you cun retreve the ClD
lor un obect usng the REF() luncton. lor exumpe, the loowng query retreves the ClD lor
customer rl n the object_customers tube:
SELECT REF(oc)
FROM object_customers oc
WHERE oc.id = 1;
REF(OC)
---------------------------------------------------------------------
0000280209D66AB93F991647649D78D08B267EE44858C7B9989D9D40689FB4DA92820
AFFE2010003280000
1he ong strng ol numbers und etters ure the ClD, whch dentles the ocuton ol the obect
n the dutubuse. You cun store un ClD n un obect relerence und uter uccess the obect t relers
to. An obect relerence, whch s smur to u ponter n C++, ponts to un obect stored n un
obect tube usng the ClD. You muy use obect relerences to mode reutonshps between obect
tubes, und, us you' see uter, you cun use obect relerences n lL/SQL to uccess obects.
You use the REF type to delne un obect relerence, the loowng stutement creutes u tube
numed purchases thut contuns two obect relerence coumns numed customer_ref und
product_ref:
CREATE TABLE purchases (
id INTEGER PRIMARY KEY,
customer_ref REF t_person SCOPE IS object_customers,
product_ref REF t_product SCOPE IS object_products
);
1he SCOPE IS cuuse restrcts un obect relerence to pont to obects n u speclc tube. lor
exumpe, the customer_ref coumn s restrcted to pont to obects n the object_customers
tube ony, smury, the product_ref coumn s restrcted to pont to obects n the object_
products tube ony.
As l mentoned eurer, euch obect n un obect tube hus u unque obect dentler (ClD) thut
you cun store n un obect relerence, you cun retreve un ClD usng the REF() luncton und store
t n un obect relerence. lor exumpe, the loowng INSERT stutement udds u row to the purchases
tube, notce thut the REF() luncton s used n the queres to get the obect dentlers lor
customer rl und product rl lrom the object_customers und object_products tubes:
INSERT INTO purchases (
id,
customer_ref,
product_ref
) VALUES (
1,
(SELECT REF(oc) FROM object_customers oc WHERE oc.id = 1),
(SELECT REF(op) FROM object_products op WHERE op.id = 1)
);
1hs exumpe records thut customer rl purchused product rl.
Chupter l2: Dutubuse Cbects

1he loowng query seects the row lrom the purchases tube, notce thut the customer_
ref und product_ref coumns contun relerences to the obects n the object_customers
und object_products tubes:
SELECT *
FROM purchases;
ID
----------
CUSTOMER_REF
---------------------------------------------------------------------
PRODUCT_REF
---------------------------------------------------------------------
1
0000220208D66AB93F991647649D78D08B267EE44858C7B9989D9D40689FB4DA92820
AFFE2
0000220208662E2AB4256711D6A1B50010A4E7AE8A662E2AB2256711D6A1B50010A4E
7AE8A
You cun retreve the uctuu obects stored n un obect relerence usng the DEREF() luncton,
whch uccepts un obect relerence us u purumeter und returns the uctuu obect. lor exumpe, the
loowng query uses DEREF() to retreve customer rl und product rl through the customer_
ref und product_ref coumns ol the purchases tube:
SELECT DEREF(customer_ref), DEREF(product_ref)
FROM purchases;
DEREF(CUSTOMER_REF)(ID, FIRST_NAME, LAST_NAME, DOB, PHONE,
ADDRESS(STREET, CITY,
----------------------------------------------------------
DEREF(PRODUCT_REF)(ID, NAME, DESCRIPTION, PRICE, DAYS_VALID)
------------------------------------------------------------
T_PERSON(1, 'John', 'Brown', '01-FEB-55', '800-555-1211',
T_ADDRESS('2 State Street', 'Beantown', 'MA', '12345'))
T_PRODUCT(1, 'pasta', '20 oz bag of pasta', 3.95, 10)
1he next query retreves the customer's first_name und address.street uttrbutes, pus
the product's name uttrbute:
SELECT DEREF(customer_ref).first_name,
DEREF(customer_ref).address.street, DEREF(product_ref).name
FROM purchases;
DEREF(CUST DEREF(CUSTOMER_ DEREF(PROD
---------- --------------- ----------
John 2 State Street pasta
1he loowng UPDATE stutement modles the product_ref coumn to pont to product r2:
UPDATE purchases SET product_ref = (
SELECT REF(op) FROM object_products op WHERE op.id = 2
) WHERE id = 1;
1 row updated.
392
Cruce Dutubuse ll SQL
1he loowng query verles ths chunge:
SELECT DEREF(customer_ref), DEREF(product_ref)
FROM purchases;
DEREF(CUSTOMER_REF)(ID, FIRST_NAME, LAST_NAME, DOB, PHONE,
ADDRESS(STREET, CITY,
----------------------------------------------------------
DEREF(PRODUCT_REF)(ID, NAME, DESCRIPTION, PRICE, DAYS_VALID)
------------------------------------------------------------
T_PERSON(1, 'John', 'Brown', '01-FEB-55', '800-555-1211',
T_ADDRESS('2 State Street', 'Beantown', 'MA', '12345'))
T_PRODUCT(2, 'sardines', '12 oz box of sardines', 2.99, 5)
Cumparing Objcct VaIucs
You cun compure the vuue ol two obects n u WHERE cuuse ol u query usng the equuty
operutor (=). lor exumpe, the loowng query retreves customer rl lrom the object_
customers tube:
SELECT oc.id, oc.first_name, oc.last_name, oc.dob
FROM object_customers oc
WHERE VALUE(oc) =
t_person(1, 'John', 'Brown', '01-FEB-1955', '800-555-1211',
t_address('2 State Street', 'Beantown', 'MA', '12345')
);
ID FIRST_NAME LAST_NAME DOB
---------- ---------- ---------- ---------
1 John Brown 01-FEB-55
1he next query retreves product rl lrom the object_products tube:
SELECT op.id, op.name, op.price, op.days_valid
FROM object_products op
WHERE VALUE(op) = t_product(1, 'pasta', '20 oz bag of pasta', 3.95, 10);
ID NAME PRICE DAYS_VALID
---------- ---------- ---------- ----------
1 pasta 3.95 10
You cun uso use the <> und IN operutors n the WHERE cuuse:
SELECT oc.id, oc.first_name, oc.last_name, oc.dob
FROM object_customers oc
WHERE VALUE(oc) <>
t_person(1, 'John', 'Brown', '01-FEB-1955', '800-555-1211',
t_address('2 State Street', 'Beantown', 'MA', '12345')
);
ID FIRST_NAME LAST_NAME DOB
---------- ---------- ---------- ---------
2 Cynthia Green 05-FEB-68
Chupter l2: Dutubuse Cbects

SELECT op.id, op.name, op.price, op.days_valid


FROM object_products op
WHERE VALUE(op) IN t_product(1, 'pasta', '20 oz bag of pasta', 3.95, 10);
ID NAME PRICE DAYS_VALID
---------- ---------- ---------- ----------
1 pasta 3.95 10
ll you wunt to use un operutor ke <, >, <=, >=, LIKE, or BETWEEN, you need to provde u
mup luncton lor the type. A mup luncton must return u snge vuue ol one ol the but-n types
thut the dutubuse cun then use to compure two obects. 1he vuue returned by the mup luncton
w be dllerent lor every obect type, und you need to lgure out whut the best uttrbute, or
concutenuton ol uttrbutes, represents un obect's vuue. lor exumpe, wth the t_product type,
l'd return the price uttrbute, wth the t_person type, l'd return u concutenuton ol the last_
name und first_name uttrbutes.
1he loowng stutements creute u type numed t_person2 thut contuns u mup luncton
numed get_string(), notce thut get_string() returns u VARCHAR2 strng contunng u
concutenuton ol the last_name und first_name uttrbutes:
CREATE TYPE t_person2 AS OBJECT (
id INTEGER,
first_name VARCHAR2(10),
last_name VARCHAR2(10),
dob DATE,
phone VARCHAR2(12),
address t_address,
-- declare the get_string() map function,
-- which returns a VARCHAR2 string
MAP MEMBER FUNCTION get_string RETURN VARCHAR2
);
/
CREATE TYPE BODY t_person2 AS
-- define the get_string() map function
MAP MEMBER FUNCTION get_string RETURN VARCHAR2 IS
BEGIN
-- return a concatenated string containing the
-- last_name and first_name attributes
RETURN last_name || ' ' || first_name;
END get_string;
END;
/
As you' see shorty, the dutubuse w uutomutcuy cu get_string() when compurng
t_person2 obects.
1he loowng stutements creute u tube numed object_customers2 und udd rows to t:
CREATE TABLE object_customers2 OF t_person2;
INSERT INTO object_customers2 VALUES (
394
Cruce Dutubuse ll SQL
t_person2(1, 'John', 'Brown', '01-FEB-1955', '800-555-1211',
t_address('2 State Street', 'Beantown', 'MA', '12345')
)
);
INSERT INTO object_customers2 VALUES (
t_person2(2, 'Cynthia', 'Green', '05-FEB-1968', '800-555-1212',
t_address('3 Free Street', 'Middle Town', 'CA', '12345')
)
);
1he loowng query uses > n the WHERE cuuse:
SELECT oc2.id, oc2.first_name, oc2.last_name, oc2.dob
FROM object_customers2 oc2
WHERE VALUE(oc2) >
t_person2(1, 'John', 'Brown', '01-FEB-1955', '800-555-1211',
t_address('2 State Street', 'Beantown', 'MA', '12345')
);
ID FIRST_NAME LAST_NAME DOB
---------- ---------- ---------- ---------
2 Cynthia Green 05-FEB-68
\hen the query s executed, the dutubuse uutomutcuy cus get_string() to compure
the obects n the object_customers2 tube to the obect ulter the > n the WHERE cuuse. 1he
get_string() luncton returns u concutenuton ol the last_name und first_name uttrbutes
ol the obects, und becuuse Green Cynthia s greuter thun Brown John, she s returned by
the query.
Using Objccts in Pl/SQl
You cun creute und munpuute obects n lL/SQL. ln ths secton, you' see the use ol u puckuge
numed product_package, whch s creuted when you run the object_schema.sql scrpt,
product_package contuns the loowng methods:
A luncton numed get_products() thut returns u REF CURSOR thut ponts to the
obects n the object_products tube
A procedure numed display_product() thut dspuys the uttrbutes ol u snge obect
n the object_products tube
A procedure numed insert_product() thut udds un obect to the object_
products tube
A procedure numed update_product_price() thut updutes the price uttrbute
ol un obect n the object_products tube
A luncton numed get_product() thut returns u snge obect lrom the object_
products tube
A procedure numed update_product() thut updutes u the uttrbutes ol un obect n
the object_products tube
Chupter l2: Dutubuse Cbects
39S
A luncton numed get_product_ref() thut returns u relerence to u snge obect lrom
the object_products tube
A procedure numed delete_product() thut deetes u snge obect lrom the object_
products tube
1he object_schema.sql scrpt contuns the loowng puckuge speclcuton:
CREATE PACKAGE product_package AS
TYPE t_ref_cursor IS REF CURSOR;
FUNCTION get_products RETURN t_ref_cursor;
PROCEDURE display_product(
p_id IN object_products.id%TYPE
);
PROCEDURE insert_product(
p_id IN object_products.id%TYPE,
p_name IN object_products.name%TYPE,
p_description IN object_products.description%TYPE,
p_price IN object_products.price%TYPE,
p_days_valid IN object_products.days_valid%TYPE
);
PROCEDURE update_product_price(
p_id IN object_products.id%TYPE,
p_factor IN NUMBER
);
FUNCTION get_product(
p_id IN object_products.id%TYPE
) RETURN t_product;
PROCEDURE update_product(
p_product t_product
);
FUNCTION get_product_ref(
p_id IN object_products.id%TYPE
) RETURN REF t_product;
PROCEDURE delete_product(
p_id IN object_products.id%TYPE
);
END product_package;
/
You' see the methods n the body ol product_package n the loowng sectons.
Thc gct_pruducts() functiun
1he get_products() luncton returns u REF CURSOR thut ponts to the obects n the
object_products tube, get_products() s delned us loows n the body ol product_
package:
FUNCTION get_products
RETURN t_ref_cursor IS
-- declare a t_ref_cursor object
v_products_ref_cursor t_ref_cursor;
BEGIN
396
Cruce Dutubuse ll SQL
-- get the REF CURSOR
OPEN v_products_ref_cursor FOR
SELECT VALUE(op)
FROM object_products op
ORDER BY op.id;
-- return the REF CURSOR
RETURN v_products_ref_cursor;
END get_products;
1he loowng query cus product_package.get_products() to retreve the products
lrom object_products:
SELECT product_package.get_products
FROM dual;
GET_PRODUCTS
--------------------
CURSOR STATEMENT : 1
CURSOR STATEMENT : 1
VALUE(OP)(ID, NAME, DESCRIPTION, PRICE, DAYS_VALID)
----------------------------------------------------------
T_PRODUCT(1, 'pasta', '20 oz bag of pasta', 3.95, 10)
T_PRODUCT(2, 'sardines', '12 oz box of sardines', 2.99, 5)
Thc dispIay_pruduct() Pruccdurc
1he display_product() procedure dspuys the uttrbutes ol u snge obect n the object_
products tube, display_product() s delned us loows n the body ol product_package:
PROCEDURE display_product(
p_id IN object_products.id%TYPE
) AS
-- declare a t_product object named v_product
v_product t_product;
BEGIN
-- attempt to get the product and store it in v_product
SELECT VALUE(op)
INTO v_product
FROM object_products op
WHERE id = p_id;
-- display the attributes of v_product
DBMS_OUTPUT.PUT_LINE('v_product.id=' ||
v_product.id);
DBMS_OUTPUT.PUT_LINE('v_product.name=' ||
v_product.name);
DBMS_OUTPUT.PUT_LINE('v_product.description=' ||
v_product.description);
DBMS_OUTPUT.PUT_LINE('v_product.price=' ||
Chupter l2: Dutubuse Cbects
397
v_product.price);
DBMS_OUTPUT.PUT_LINE('v_product.days_valid=' ||
v_product.days_valid);
-- call v_product.get_sell_by_date() and display the date
DBMS_OUTPUT.PUT_LINE('Sell by date=' ||
v_product.get_sell_by_date());
END display_product;
1he loowng exumpe cus product_package.display_product(1) to retreve
product rl lrom the object_products tube:
SET SERVEROUTPUT ON
CALL product_package.display_product(1);
v_product.id=1
v_product.name=pasta
v_product.description=20 oz bag of pasta
v_product.price=3.95
v_product.days_valid=10
Sell by date=25-JUN-07
Thc inscrt_pruduct() Pruccdurc
1he insert_product() procedure udds un obect to the object_products tube, insert_
product() s delned us loows n the body ol product_package:
PROCEDURE insert_product(
p_id IN object_products.id%TYPE,
p_name IN object_products.name%TYPE,
p_description IN object_products.description%TYPE,
p_price IN object_products.price%TYPE,
p_days_valid IN object_products.days_valid%TYPE
) AS
-- create a t_product object named v_product
v_product t_product :=
t_product(
p_id, p_name, p_description, p_price, p_days_valid
);
BEGIN
-- add v_product to the object_products table
INSERT INTO object_products VALUES (v_product);
COMMIT;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
END insert_product;
1he loowng exumpe cus product_package.insert_product() to udd u new obect
to the object_products tube:
CALL product_package.insert_product(3, 'salsa',
'15 oz jar of salsa', 1.50, 20);
398
Cruce Dutubuse ll SQL
Thc updatc_pruduct_pricc() Pruccdurc
1he update_product_price() procedure updutes the prce uttrbute ol un obect n the
object_products tube, update_product_price() s delned us loows n the body ol
product_package:
PROCEDURE update_product_price(
p_id IN object_products.id%TYPE,
p_factor IN NUMBER
) AS
-- declare a t_product object named v_product
v_product t_product;
BEGIN
-- attempt to select the product for update and
-- store the product in v_product
SELECT VALUE(op)
INTO v_product
FROM object_products op
WHERE id = p_id
FOR UPDATE;
-- display the current price of v_product
DBMS_OUTPUT.PUT_LINE('v_product.price=' ||
v_product.price);
-- multiply v_product.price by p_factor
v_product.price := v_product.price * p_factor;
DBMS_OUTPUT.PUT_LINE('New v_product.price=' ||
v_product.price);
-- update the product in the object_products table
UPDATE object_products op
SET op = v_product
WHERE id = p_id;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
END update_product_price;
1he loowng exumpe cus product_package.update_product_price() to updute
the prce ol product r3 n the object_products tube:
CALL product_package.update_product_price(3, 2.4);
v_product.price=1.5
New v_product.price=3.6
Thc gct_pruduct() functiun
1he get_product() luncton returns u snge obect lrom the object_products tube, get_
product() s delned us loows n the body ol product_package:
Chupter l2: Dutubuse Cbects
399
FUNCTION get_product(
p_id IN object_products.id%TYPE
)
RETURN t_product IS
-- declare a t_product object named v_product
v_product t_product;
BEGIN
-- get the product and store it in v_product
SELECT VALUE(op)
INTO v_product
FROM object_products op
WHERE op.id = p_id;
-- return v_product
RETURN v_product;
END get_product;
1he loowng query cus product_package.get_product() to get product r3 lrom the
object_products tube:
SELECT product_package.get_product(3)
FROM dual;
PRODUCT_PACKAGE.GET_PRODUCT(3)(ID, NAME, DESCRIPTION
----------------------------------------------------
T_PRODUCT(3, 'salsa', '15 oz jar of salsa', 3.6, 20)
Thc updatc_pruduct() Pruccdurc
1he update_product() procedure updutes u the uttrbutes ol un obect n the object_
products tube, update_product() s delned us loows n the body ol product_package:
PROCEDURE update_product(
p_product IN t_product
) AS
BEGIN
-- update the product in the object_products table
UPDATE object_products op
SET op = p_product
WHERE id = p_product.id;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
END update_product;
1he loowng exumpe cus product_package.update_product() to updute product
r3 n the object_products tube:
CALL product_package.update_product(t_product(3, 'salsa',
'25 oz jar of salsa', 2.70, 15));
400
Cruce Dutubuse ll SQL
Thc gct_pruduct_rcf() functiun
1he get_product_ref() luncton returns u relerence to u snge obect lrom the object_
products tube, get_product_ref() s delned us loows n the body ol product_package:
FUNCTION get_product_ref(
p_id IN object_products.id%TYPE
)
RETURN REF t_product IS
-- declare a reference to a t_product
v_product_ref REF t_product;
BEGIN
-- get the REF for the product and
-- store it in v_product_ref
SELECT REF(op)
INTO v_product_ref
FROM object_products op
WHERE op.id = p_id;
-- return v_product_ref
RETURN v_product_ref;
END get_product_ref;
1he loowng query cus product_package.get_product_ref() to get the relerence
to product r3 lrom the object_products tube:
SELECT product_package.get_product_ref(3)
FROM dual;
PRODUCT_PACKAGE.GET_PRODUCT_REF(3)
------------------------------------------------------------------------------
000028020956DBE8BEFDEF4D5BA8C806A7B31B49DF916CDB2CAC1B46E9808BA181F9F2760F0100
033D0002
1he next exumpe cus product_package.get_product_ref() ugun, ths tme usng
DEREF() to get to the uctuu product:
SELECT DEREF(product_package.get_product_ref(3))
FROM dual;
DEREF(PRODUCT_PACKAGE.GET_PRODUCT_REF(3))(ID, NAME,
----------------------------------------------------
T_PRODUCT(3, 'salsa', '25 oz jar of salsa', 2.7, 15)
Thc dcIctc_pruduct() Pruccdurc
1he delete_product() procedure deetes u snge obect lrom the object_products tube,
delete_product() s delned us loows n the body ol product_package:
PROCEDURE delete_product(
p_id IN object_products.id%TYPE
) AS
BEGIN
Chupter l2: Dutubuse Cbects
401
-- delete the product
DELETE FROM object_products op
WHERE op.id = p_id;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
END delete_product;
1he loowng exumpe cus product_package.delete_product() to deete product
r3 lrom the object_products tube:
CALL product_package.delete_product(3);
Now thut you've seen u the methods n product_package, t's tme lor you to see two
procedures numed product_lifecycle() und product_lifecycle2() thut cu the
vurous methods n the puckuge. oth procedures ure creuted when you run the object_
schema.sql scrpt.
Thc pruduct_IifccycIc() Pruccdurc
1he product_lifecycle() procedure s delned us loows:
CREATE PROCEDURE product_lifecycle AS
-- declare object
v_product t_product;
BEGIN
-- insert a new product
product_package.insert_product(4, 'beef',
'25 lb pack of beef', 32, 10);
-- display the product
product_package.display_product(4);
-- get the new product and store it in v_product
SELECT product_package.get_product(4)
INTO v_product
FROM dual;
-- change some attributes of v_product
v_product.description := '20 lb pack of beef';
v_product.price := 36;
v_product.days_valid := 8;
-- update the product
product_package.update_product(v_product);
-- display the product
product_package.display_product(4);
-- delete the product
product_package.delete_product(4);
END product_lifecycle;
/
402
Cruce Dutubuse ll SQL
1he loowng exumpe cus product_lifecycle():
CALL product_lifecycle();
v_product.id=4
v_product.name=beef
v_product.description=25 lb pack of beef
v_product.price=32
v_product.days_valid=10
Sell by date=27-JUN-07
v_product.id=4
v_product.name=beef
v_product.description=20 lb pack of beef
v_product.price=36
v_product.days_valid=8
Sell by date=25-JUN-07
Thc pruduct_IifccycIc2() Pruccdurc
1he product_lifecycle2() procedure uses un obect relerence to uccess u product,
product_lifecycle2() s delned us loows:
CREATE PROCEDURE product_lifecycle2 AS
-- declare object
v_product t_product;
-- declare object reference
v_product_ref REF t_product;
BEGIN
-- insert a new product
product_package.insert_product(4, 'beef',
'25 lb pack of beef', 32, 10);
-- display the product
product_package.display_product(4);
-- get the new product reference and store it in v_product_ref
SELECT product_package.get_product_ref(4)
INTO v_product_ref
FROM dual;
-- dereference v_product_ref using the following query
SELECT DEREF(v_product_ref)
INTO v_product
FROM dual;
-- change some attributes of v_product
v_product.description := '20 lb pack of beef';
v_product.price := 36;
v_product.days_valid := 8;
-- update the product
product_package.update_product(v_product);
Chupter l2: Dutubuse Cbects
403
-- display the product
product_package.display_product(4);
-- delete the product
product_package.delete_product(4);
END product_lifecycle2;
/
Cne pont to note n ths procedure s thut, n order to derelerence v_product_ref, you
huve to use the loowng query:
SELECT DEREF(v_product_ref)
INTO v_product
FROM dual;
1he reuson you huve to use ths query s thut you cunnot use DEREF() drecty n lL/SQL
code. lor exumpe, the loowng stutement won't compe n lL/SQL:
v_product := DEREF(v_product_ref);
1he loowng exumpe cus product_lifecycle2():
CALL product_lifecycle2();
v_product.id=4
v_product.name=beef
v_product.description=25 lb pack of beef
v_product.price=32
v_product.days_valid=10
Sell by date=27-JUN-07
v_product.id=4
v_product.name=beef
v_product.description=20 lb pack of beef
v_product.price=36
v_product.days_valid=8
Sell by date=25-JUN-07
Typc lnhcritancc
Cruce Dutubuse 9 ntroduced obect type , whch uows you to delne herurches ol
obect types. lor exumpe, you mght wunt to delne u busness person obect type und huve thut
type nhert the exstng uttrbutes lrom t_person. 1he busness person type coud extend t_
person wth uttrbutes to store the person's ob tte und the nume ol the compuny they work lor.
lor t_person to be nherted lrom, the t_person delnton must ncude the NOT FINAL cuuse:
CREATE TYPE t_person AS OBJECT (
id INTEGER,
first_name VARCHAR2(10),
last_name VARCHAR2(10),
dob DATE,
phone VARCHAR2(12),
address t_address,
MEMBER FUNCTION display_details RETURN VARCHAR2
) NOT FINAL;
/

Cruce Dutubuse llg SQL
1he NOT FINAL cuuse ndcutes thut t_person cun be nherted lrom when delnng
unother type. (1he deluut when delnng types s FINAL, meunng thut the obect type cunnot
be nherted lrom.)
1he loowng stutement creutes the body lor t_person, notce thut the display_details()
luncton returns u VARCHAR2 contunng the id und name ol the person:
CREATE TYPE BODY t_person AS
MEMBER FUNCTION display_details RETURN VARCHAR2 IS
BEGIN
RETURN 'id=' || id || ', name=' || first_name || ' ' || last_name;
END;
END;
/

'vc provdcd an S*u crp| namcd object_schema2.sql,


vhch crca|c a |hc |cm hovn n |h and |hc |oovng cc|on.
You can run |hc crp| | ,ou arc ung Cracc Da|abac 9 or abovc.
A||cr |hc crp| compc|c, ,ou v bc oggcd n a object_user2.
1o huve u new type nhert uttrbutes und methods lrom un exstng type, you use the
UNDER keyword when delnng your new type. Cur busness person type, whch l' nume t_
business_person, uses the UNDER keyword to nhert the uttrbutes lrom t_person:
CREATE TYPE t_business_person UNDER t_person (
title VARCHAR2(20),
company VARCHAR2(20)
);
/
ln ths exumpe, t_person s known us the upcr|,pc, und t_business_person s known
us the ub|,pc. You cun then use t_business_person when delnng coumn obects or obect
tubes. lor exumpe, the loowng stutement creutes un obect tube numed object_business_
customers:
CREATE TABLE object_business_customers OF t_business_person;
1he loowng INSERT stutement udds un obect to object_business_customers,
notce thut the two uddtonu title und company uttrbutes ure supped ut the end ol the
t_business_person constructor:
INSERT INTO object_business_customers VALUES (
t_business_person(1, 'John', 'Brown', '01-FEB-1955', '800-555-1211',
t_address('2 State Street', 'Beantown', 'MA', '12345'),
'Manager', 'XYZ Corp'
)
);
1he loowng query retreves ths obect:
SELECT *
FROM object_business_customers
WHERE id = 1;
Chupter l2: Dutubuse Cbects
40S
ID FIRST_NAME LAST_NAME DOB PHONE
---------- ---------- ---------- --------- ------------
ADDRESS(STREET, CITY, STATE, ZIP)
------------------------------------------------------
TITLE COMPANY
-------------------- --------------------
1 John Brown 01-FEB-55 800-555-1211
T_ADDRESS('2 State Street', 'Beantown', 'MA', '12345')
Manager XYZ Corp
1he loowng query cus the display_details() luncton lor ths obect:
SELECT o.display_details()
FROM object_business_customers o
WHERE id = 1;
O.DISPLAY_DETAILS()
---------------------
id=1, name=John Brown
\hen you cu u method, the dutubuse seurches lor thut method n the subtype lrst, l the
method sn't lound, the supertype s seurched. ll you huve u herurchy ol types, the dutubuse w
seurch lor the method up the herurchy, l the method cunnot be lound, the dutubuse w report
un error.
Using a Subtypc Objcct in PIacc
uf a Supcrtypc Objcct
ln ths secton you' see how you cun use u subtype obect n puce ol u supertype obect, dong
ths gves you greut lexbty when storng und munpuutng reuted types. ln the exumpes, you'
see how you use u t_business_person obect (u subtype obect) n puce ol u t_person
obect (u supertype obect).
SQl fxampIcs
1he loowng stutement creutes u tube numed object_customers ol type t_person:
CREATE TABLE object_customers OF t_person;
1he loowng INSERT stutement udds u t_person obect to ths tube (the nume s }uson
ond):
INSERT INTO object_customers VALUES (
t_person(1, 'Jason', 'Bond', '03-APR-1965', '800-555-1212',
t_address('21 New Street', 'Anytown', 'CA', '12345')
)
);
1here's nothng unusuu ubout the prevous stutement: 1he INSERT smpy udds u t_person
obect to the object_customers tube. Now, becuuse the object_customers tube stores
obects ol type t_person, und t_person s u supertype ol t_business_person, you cun
406
Cruce Dutubuse ll SQL
store u t_business_person obect n object_customers, the loowng INSERT shows
ths, uddng u customer numed Steve Edwards:
INSERT INTO object_customers VALUES (
t_business_person(2, 'Steve', 'Edwards', '03-MAR-1955', '800-555-1212',
t_address('1 Market Street', 'Anytown', 'VA', '12345'),
'Manager', 'XYZ Corp'
)
);
1he object_customers tube now contuns two obects: the t_person obect udded
eurer (}uson ond) und the new t_business_person obect (Steve Ldwurds). 1he loowng
query retreves these two obects, notce thut the title und company uttrbutes lor Steve
Ldwurds ure mssng lrom the output:
SELECT *
FROM object_customers o;
ID FIRST_NAME LAST_NAME DOB PHONE
---------- ---------- ---------- --------- ------------
ADDRESS(STREET, CITY, STATE, ZIP)
------------------------------------------------------
1 Jason Bond 03-APR-65 800-555-1212
T_ADDRESS('21 New Street', 'Anytown', 'CA', '12345')
2 Steve Edwards 03-MAR-55 800-555-1212
T_ADDRESS('1 Market Street', 'Anytown', 'VA', '12345')
You cun get the lu set ol uttrbutes lor Steve Edwards by usng VALUE() n the query, us
shown n the loowng exumpe, notce the dllerent types ol the obects lor Jason Bond (u t_
person obect) und Steve Edwards (u t_business_person obect) und thut the title und
company uttrbutes lor Steve Edwards now uppeur n the output:
SELECT VALUE(o)
FROM object_customers o;
VALUE(O)(ID, FIRST_NAME, LAST_NAME, DOB, PHONE,
ADDRESS(STREET, CITY, STATE, ZIP
---------------------------------------------------------------------
T_PERSON(1, 'Jason', 'Bond', '03-APR-65', '800-555-1212',
T_ADDRESS('21 New Street', 'Anytown', 'CA', '12345'))
T_BUSINESS_PERSON(2, 'Steve', 'Edwards', '03-MAR-55', '800-555-1212',
T_ADDRESS('1 Market Street', 'Anytown', 'VA', '12345'),
'Manager', 'XYZ Corp')
Pl/SQl fxampIcs
You cun uso munpuute subtype und supertype obects n lL/SQL. lor exumpe, the loowng
procedure numed subtypes_and_supertypes() munpuutes t_business_person und
t_person obects:
CREATE PROCEDURE subtypes_and_supertypes AS
-- create objects
Chupter l2: Dutubuse Cbects
407
v_business_person t_business_person :=
t_business_person(
1, 'John', 'Brown',
'01-FEB-1955', '800-555-1211',
t_address('2 State Street', 'Beantown', 'MA', '12345'),
'Manager', 'XYZ Corp'
);
v_person t_person :=
t_person(1, 'John', 'Brown', '01-FEB-1955', '800-555-1211',
t_address('2 State Street', 'Beantown', 'MA', '12345'));
v_business_person2 t_business_person;
v_person2 t_person;
BEGIN
-- assign v_business_person to v_person2
v_person2 := v_business_person;
DBMS_OUTPUT.PUT_LINE('v_person2.id = ' || v_person2.id);
DBMS_OUTPUT.PUT_LINE('v_person2.first_name = ' ||
v_person2.first_name);
DBMS_OUTPUT.PUT_LINE('v_person2.last_name = ' ||
v_person2.last_name);
-- the following lines will not compile because v_person2
-- is of type t_person, and t_person does not know about the
-- additional title and company attributes
-- DBMS_OUTPUT.PUT_LINE('v_person2.title = ' ||
-- v_person2.title);
-- DBMS_OUTPUT.PUT_LINE('v_person2.company = ' ||
-- v_person2.company);
-- the following line will not compile because you cannot
-- directly assign a t_person object to a t_business_person
-- object
-- v_business_person2 := v_person;
END subtypes_and_supertypes;
/
1he loowng exumpe shows the resut ol cung subtypes_and_supertypes():
SET SERVEROUTPUT ON
CALL subtypes_and_supertypes();
v_person2.id = 1
v_person2.first_name = John
v_person2.last_name = Brown
NOT SUBSTlTUTABlf Objccts
ll you wunt to prevent the use ol u subtype obect n puce ol u supertype obect, you cun murk un
obect tube or obect coumn us not substtutube, lor exumpe, the loowng stutement creutes
u tube numed object_customers2:
CREATE TABLE object_customers_not_subs OF t_person
NOT SUBSTITUTABLE AT ALL LEVELS;
408
Cruce Dutubuse ll SQL
1he NOT SUBSTITUTABLE AT ALL LEVELS cuuse ndcutes thut no obects ol u type
other thun t_person cun be nserted nto the tube. ll un uttempt s mude to udd un obect ol
type t_business_person to ths tube, un error s returned:
SQL> INSERT INTO object_customers_not_subs VALUES (
2 t_business_person(1, 'Steve', 'Edwards', '03-MAR-1955', '800-555-1212',
3 t_address('1 Market Street', 'Anytown', 'VA', '12345'),
4 'Manager', 'XYZ Corp'
5 )
6 );
t_business_person(1, 'Steve', 'Edwards', '03-MAR-1955', '800-555-1212',
*
ERROR at line 2:
ORA-00932: inconsistent datatypes: expected OBJECT_USER2.T_PERSON got
OBJECT_USER2.T_BUSINESS_PERSON
You cun uso murk un obect coumn us not substtutube, lor exumpe, the loowng
stutement creutes u tube wth un obect coumn numed product thut cun store ony obects ol
type t_product:
CREATE TABLE products (
product t_product,
quantity_in_stock INTEGER
)
COLUMN product NOT SUBSTITUTABLE AT ALL LEVELS;
Any uttempts to udd un obect not ol type t_product to the product coumn w resut n
un error.
Othcr UscfuI Objcct functiuns
ln the eurer sectons ol ths chupter you suw the use ol the REF(), DEREF(), und VALUE()
lunctons. ln ths secton, you' see the loowng uddtonu lunctons thut muy be used wth obects:
IS OF() checks l un obect s ol u purtcuur type or subtype.
TREAT() does u run-tme check to see l un obect's type muy be treuted us u supertype.
SYS_TYPEID() returns the lD ol un obect's type.
lS Of()
You use IS OF() to check whether un obect s ol u purtcuur type or subtype. lor exumpe,
the loowng query uses IS OF() to check whether the obects n the object_business_
customers tube ure ol type t_business_personbecuuse they ure, u row s returned by
the query:
SELECT VALUE(o)
FROM object_business_customers o
WHERE VALUE(o) IS OF (t_business_person);
VALUE(O)(ID, FIRST_NAME, LAST_NAME, DOB, PHONE,
ADDRESS(STREET, CITY, STATE, ZIP
------------------------------------------------------------------
Chupter l2: Dutubuse Cbects

T_BUSINESS_PERSON(1, 'John', 'Brown', '01-FEB-55', '800-555-1211',


T_ADDRESS('2 State Street', 'Beantown', 'MA', '12345'),
'Manager', 'XYZ Corp')
You cun uso use IS OF() to check whether un obect s ol u subtype ol the specled
type. lor exumpe, the obects n the object_business_customers tube ure ol type t_
business_person, whch s u subtype ol t_person, therelore, the loowng query returns
the sume resut us thut shown n the prevous exumpe:
SELECT VALUE(o)
FROM object_business_customers o
WHERE VALUE(o) IS OF (t_person);
VALUE(O)(ID, FIRST_NAME, LAST_NAME, DOB, PHONE,
ADDRESS(STREET, CITY, STATE, ZIP
------------------------------------------------------------------
T_BUSINESS_PERSON(1, 'John', 'Brown', '01-FEB-55', '800-555-1211',
T_ADDRESS('2 State Street', 'Beantown', 'MA', '12345'),
'Manager', 'XYZ Corp')
You cun ncude more thun one type n IS OF(), lor exumpe:
SELECT VALUE(o)
FROM object_business_customers o
WHERE VALUE(o) IS OF (t_business_person, t_person);
VALUE(O)(ID, FIRST_NAME, LAST_NAME, DOB, PHONE,
ADDRESS(STREET, CITY, STATE, ZIP
------------------------------------------------------------------
T_BUSINESS_PERSON(1, 'John', 'Brown', '01-FEB-55', '800-555-1211',
T_ADDRESS('2 State Street', 'Beantown', 'MA', '12345'),
'Manager', 'XYZ Corp')
ln the eurer secton entted Lsng u Subtype Cbect n luce ol u Supertype Cbect, you
suw the uddton ol u t_person obect (Jason Bond) und t_business_person obect
(Steve Edwards) to the object_customers tube. As u remnder, the loowng query shows
these obects:
SELECT VALUE(o)
FROM object_customers o;
VALUE(O)(ID, FIRST_NAME, LAST_NAME, DOB, PHONE,
ADDRESS(STREET, CITY, STATE, ZIP
---------------------------------------------------------------------
T_PERSON(1, 'Jason', 'Bond', '03-APR-65', '800-555-1212',
T_ADDRESS('21 New Street', 'Anytown', 'CA', '12345'))
T_BUSINESS_PERSON(2, 'Steve', 'Edwards', '03-MAR-55', '800-555-1212',
T_ADDRESS('1 Market Street', 'Anytown', 'VA', '12345'),
'Manager', 'XYZ Corp')
ecuuse t_business_person type s u subtype ol t_person, IS OF (t_person)
returns true when u t_business_person obect or u t_person obect s checked, ths s

Cruce Dutubuse ll SQL
ustruted n the loowng query thut retreves both Jason Bond und Steve Edwards usng
IS OF (t_person):
SELECT VALUE(o)
FROM object_customers o
WHERE VALUE(o) IS OF (t_person);
VALUE(O)(ID, FIRST_NAME, LAST_NAME, DOB, PHONE,
ADDRESS(STREET, CITY, STATE, ZIP
---------------------------------------------------------------------
T_PERSON(1, 'Jason', 'Bond', '03-APR-65', '800-555-1212',
T_ADDRESS('21 New Street', 'Anytown', 'CA', '12345'))
T_BUSINESS_PERSON(2, 'Steve', 'Edwards', '03-MAR-55', '800-555-1212',
T_ADDRESS('1 Market Street', 'Anytown', 'VA', '12345'),
'Manager', 'XYZ Corp')
You cun uso use the ONLY keyword n conuncton wth IS OF () to check lor obects ol
u speclc type ony: IS OF () returns false lor obects ol unother type n the herurchy. lor
exumpe, IS OF (ONLY t_person) returns true lor obects ol type t_person ony und
returns false lor obects ol type t_business_person. ln ths wuy, you cun use IS OF
(ONLY t_person) to restrct the obect returned by u query ugunst the object_customers
tube to Jason Bond, us shown n the loowng exumpe:
SELECT VALUE(o)
FROM object_customers o
WHERE VALUE(o) IS OF (ONLY t_person);
VALUE(O)(ID, FIRST_NAME, LAST_NAME, DOB, PHONE,
ADDRESS(STREET, CITY, STATE, ZIP
---------------------------------------------------------
T_PERSON(1, 'Jason', 'Bond', '03-APR-65', '800-555-1212',
T_ADDRESS('21 New Street', 'Anytown', 'CA', '12345'))
Smury, IS OF(ONLY t_business_person) returns true lor obects ol type t_
business_person ony, und returns false lor obects ol type t_person. lor exumpe,
the loowng query retreves the t_business_person obect ony und therelore Steve
Edwards s returned:
SELECT VALUE(o)
FROM object_customers o
WHERE VALUE(o) IS OF (ONLY t_business_person);
VALUE(O)(ID, FIRST_NAME, LAST_NAME, DOB, PHONE,
ADDRESS(STREET, CITY, STATE, ZIP
---------------------------------------------------------------------
T_BUSINESS_PERSON(2, 'Steve', 'Edwards', '03-MAR-55', '800-555-1212',
T_ADDRESS('1 Market Street', 'Anytown', 'VA', '12345'),
'Manager', 'XYZ Corp')
You cun ncude mutpe types ulter ONLY. lor exumpe, IS OF (ONLY t_person, t_
business_person) returns true lor t_person und t_business_person obects ony, the
loowng query shows ths by returnng, us expected, both Jason Bond und Steve Edwards:
Chupter l2: Dutubuse Cbects

SELECT VALUE(o)
FROM object_customers o
WHERE VALUE(o) IS OF (ONLY t_person, t_business_person);
VALUE(O)(ID, FIRST_NAME, LAST_NAME, DOB, PHONE,
ADDRESS(STREET, CITY, STATE, ZIP
---------------------------------------------------------------------
T_PERSON(1, 'Jason', 'Bond', '03-APR-65', '800-555-1212',
T_ADDRESS('21 New Street', 'Anytown', 'CA', '12345'))
T_BUSINESS_PERSON(2, 'Steve', 'Edwards', '03-MAR-55', '800-555-1212',
T_ADDRESS('1 Market Street', 'Anytown', 'VA', '12345'),
'Manager', 'XYZ Corp')
You cun uso use IS OF() n lL/SQL. lor exumpe, the loowng procedure numed check_
types() creutes t_business_person und t_person objects, und t uses IS OF() to
check ther types:
CREATE PROCEDURE check_types AS
-- create objects
v_business_person t_business_person :=
t_business_person(
1, 'John', 'Brown',
'01-FEB-1955', '800-555-1211',
t_address('2 State Street', 'Beantown', 'MA', '12345'),
'Manager', 'XYZ Corp'
);
v_person t_person :=
t_person(1, 'John', 'Brown', '01-FEB-1955', '800-555-1211',
t_address('2 State Street', 'Beantown', 'MA', '12345'));
BEGIN
-- check the types of the objects
IF v_business_person IS OF (t_business_person) THEN
DBMS_OUTPUT.PUT_LINE('v_business_person is of type ' ||
't_business_person');
END IF;
IF v_person IS OF (t_person) THEN
DBMS_OUTPUT.PUT_LINE('v_person is of type t_person');
END IF;
IF v_business_person IS OF (t_person) THEN
DBMS_OUTPUT.PUT_LINE('v_business_person is of type t_person');
END IF;
IF v_business_person IS OF (t_business_person, t_person) THEN
DBMS_OUTPUT.PUT_LINE('v_business_person is of ' ||
'type t_business_person or t_person');
END IF;
IF v_business_person IS OF (ONLY t_business_person) THEN
DBMS_OUTPUT.PUT_LINE('v_business_person is of only ' ||
'type t_business_person');
END IF;
IF v_business_person IS OF (ONLY t_person) THEN
DBMS_OUTPUT.PUT_LINE('v_business_person is of only ' ||
412
Cruce Dutubuse ll SQL
'type t_person');
ELSE
DBMS_OUTPUT.PUT_LINE('v_business_person is not of only ' ||
'type t_person');
END IF;
END check_types;
/
1he loowng exumpe shows the resut ol cung check_types():
SET SERVEROUTPUT ON
CALL check_types();
v_business_person is of type t_business_person
v_person is of type t_person
v_business_person is of type t_person
v_business_person is of type t_business_person or t_person
v_business_person is of only type t_business_person
v_business_person is not of only type t_person
TRfAT()
You use TREAT() to do u run-tme check to see whether un obect ol u subtype muy be treuted us
un obect ol u supertype, l ths s so, TREAT() returns un obect, und l not so, TREAT() returns
nu. lor exumpe, becuuse t_business_person s u subtype ol t_person, u t_business_
person obect cun be treuted us u t_person obect, you suw ths eurer n the secton entted
Lsng u Subtype Cbect n luce ol u Supertype Cbect, where u t_business_person obect
(Steve Edwards) wus nserted nto the object_customers tube, whch normuy hods t_
person obects. 1he loowng query uses TREAT() to check thut Steve Edwards cun be
treuted us u t_person obect:
SELECT NVL2(TREAT(VALUE(o) AS t_person), 'yes', 'no')
FROM object_customers o
WHERE first_name = 'Steve' AND last_name = 'Edwards';
NVL
---
yes
NVL2() returns yes becuuse TREAT(VALUE(o) AS t_person) returns un obect (thut s,
not u nu vuue). 1hs meuns thut Steve Edwards cun be treuted us u t_person obect.
1he next query checks whether Jason Bond (u t_person obect) cun be treuted us u t_
business_person obecthe cunnot, und, therelore, TREAT() returns nu, und NVL2()
returns no:
SELECT NVL2(TREAT(VALUE(o) AS t_business_person), 'yes', 'no')
FROM object_customers o
WHERE first_name = 'Jason' AND last_name = 'Bond';
NVL
---
no
Chupter l2: Dutubuse Cbects

ecuuse TREAT() returns nu lor the whoe obect, u the ndvduu uttrbutes lor the obect
ure uso nu. lor exumpe, the loowng query uttempts to uccess the first_name uttrbute
through Jason Bondnu s returned (us expected):
SELECT
NVL2(TREAT(VALUE(o) AS t_business_person).first_name, 'not null', 'null')
FROM object_customers o
WHERE first_name = 'Jason' AND last_name = 'Bond';
NVL2
----
null
1he next query uses TREAT() to check whether Jason Bond cun be treuted us u t_person
obecthe u t_person obect und therelore yes s returned:
SELECT NVL2(TREAT(VALUE(o) AS t_person).first_name, 'yes', 'no')
FROM object_customers o
WHERE first_name = 'Jason' AND last_name = 'Bond';
NVL
---
yes
You cun uso retreve un obect through the use ol TREAT(), lor exumpe, the loowng query
retreves Steve Edwards:
SELECT TREAT(VALUE(o) AS t_business_person)
FROM object_customers o
WHERE first_name = 'Steve' AND last_name = 'Edwards';
TREAT(VALUE(O)AST_BUSINESS_PERSON)(ID, FIRST_NAME, LAST_NAME, DOB, PHONE,
ADDRESS
-------------------------------------------------------------------------
T_BUSINESS_PERSON(2, 'Steve', 'Edwards', '03-MAR-55', '800-555-1212',
T_ADDRESS('1 Market Street', 'Anytown', 'VA', '12345'),
'Manager', 'XYZ Corp')
ll you try ths query wth Jason Bond, nu s returned, us expected, therelore, nothng
uppeurs n the output ol the loowng query:
SELECT TREAT(VALUE(o) AS t_business_person)
FROM object_customers o
WHERE first_name = 'Jason' AND last_name = 'Bond';
TREAT(VALUE(O)AST_BUSINESS_PERSON)(ID, FIRST_NAME, LAST_NAME, DOB, PHONE,
ADDRESS
-------------------------------------------------------------------------
Let's tuke ook ut usng TREAT() wth the object_business_customers tube, whch
contuns the t_business_person obect John Brown:
SELECT VALUE(o)
FROM object_business_customers o;

Cruce Dutubuse ll SQL
VALUE(O)(ID, FIRST_NAME, LAST_NAME, DOB, PHONE,
ADDRESS(STREET, CITY, STATE, ZIP
------------------------------------------------------------------
T_BUSINESS_PERSON(1, 'John', 'Brown', '01-FEB-55', '800-555-1211',
T_ADDRESS('2 State Street', 'Beantown', 'MA', '12345'),
'Manager', 'XYZ Corp')
1he loowng query uses TREAT() to check whether John Brown cun be treuted us u t_
person obecthe cun, becuuse t_business_person s u subtype ol t_person, therelore,
yes s returned by the query:
SELECT NVL2(TREAT(VALUE(o) AS t_person), 'yes', 'no')
FROM object_business_customers o
WHERE first_name = 'John' AND last_name = 'Brown';
NVL
---
yes
1he loowng exumpe shows the obect returned by TREAT() when queryng the object_
business_customers tube, notce thut you st get the title und company uttrbutes lor
John Brown:
SELECT TREAT(VALUE(o) AS t_person)
FROM object_business_customers o;
TREAT(VALUE(O)AST_PERSON)(ID, FIRST_NAME, LAST_NAME, DOB, PHONE,
ADDRESS(STREET,
------------------------------------------------------------------
T_BUSINESS_PERSON(1, 'John', 'Brown', '01-FEB-55', '800-555-1211',
T_ADDRESS('2 State Street', 'Beantown', 'MA', '12345'),
'Manager', 'XYZ Corp')
You cun uso use TREAT() n lL/SQL. lor exumpe, the loowng procedure numed treat_
example() ustrutes the use ol TREAT() (you shoud study the comments n the code to
understund how TREAT() works n lL/SQL):
CREATE PROCEDURE treat_example AS
-- create objects
v_business_person t_business_person :=
t_business_person(
1, 'John', 'Brown',
'01-FEB-1955', '800-555-1211',
t_address('2 State Street', 'Beantown', 'MA', '12345'),
'Manager', 'XYZ Corp'
);
v_person t_person :=
t_person(1, 'John', 'Brown', '01-FEB-1955', '800-555-1211',
t_address('2 State Street', 'Beantown', 'MA', '12345'));
v_business_person2 t_business_person;
v_person2 t_person;
Chupter l2: Dutubuse Cbects

BEGIN
-- assign v_business_person to v_person2
v_person2 := v_business_person;
DBMS_OUTPUT.PUT_LINE('v_person2.id = ' || v_person2.id);
DBMS_OUTPUT.PUT_LINE('v_person2.first_name = ' ||
v_person2.first_name);
DBMS_OUTPUT.PUT_LINE('v_person2.last_name = ' ||
v_person2.last_name);
-- the following lines will not compile because v_person2
-- is of type t_person, and t_person does not know about the
-- additional title and company attributes
-- DBMS_OUTPUT.PUT_LINE('v_person2.title = ' ||
-- v_person2.title);
-- DBMS_OUTPUT.PUT_LINE('v_person2.company = ' ||
-- v_person2.company);
-- use TREAT when assigning v_business_person to v_person2
DBMS_OUTPUT.PUT_LINE('Using TREAT');
v_person2 := TREAT(v_business_person AS t_person);
DBMS_OUTPUT.PUT_LINE('v_person2.id = ' || v_person2.id);
DBMS_OUTPUT.PUT_LINE('v_person2.first_name = ' ||
v_person2.first_name);
DBMS_OUTPUT.PUT_LINE('v_person2.last_name = ' ||
v_person2.last_name);
-- the following lines will still not compile because v_person2
-- is of type t_person, and t_person does not know about the
-- additional title and company attributes
-- DBMS_OUTPUT.PUT_LINE('v_person2.title = ' ||
-- v_person2.title);
-- DBMS_OUTPUT.PUT_LINE('v_person2.company = ' ||
-- v_person2.company);
-- the following lines do compile because TREAT is used
DBMS_OUTPUT.PUT_LINE('v_person2.title = ' ||
TREAT(v_person2 AS t_business_person).title);
DBMS_OUTPUT.PUT_LINE('v_person2.company = ' ||
TREAT(v_person2 AS t_business_person).company);
-- the following line will not compile because you cannot
-- directly assign a t_person object to a t_business_person
-- object
-- v_business_person2 := v_person;
-- the following line throws a runtime error because you cannot
-- assign a supertype object (v_person) to a subtype object
-- (v_business_person2)
-- v_business_person2 := TREAT(v_person AS t_business_person);
END treat_example;
/
416
Cruce Dutubuse ll SQL
1he loowng exumpe shows the resut ol cung treat_example():
SET SERVEROUTPUT ON
CALL treat_example();
v_person2.id = 1
v_person2.first_name = John
v_person2.last_name = Brown
Using TREAT
v_person2.id = 1
v_person2.first_name = John
v_person2.last_name = Brown
v_person2.title = Manager
v_person2.company = XYZ Corp
SYS_TYPflD()
You use SYS_TYPEID() to get the ID ol un obect's type. lor exumpe, the loowng query uses
SYS_TYPEID() to get the ID ol the obect type n the object_business_customers tube:
SELECT first_name, last_name, SYS_TYPEID(VALUE(o))
FROM object_business_customers o;
FIRST_NAME LAST_NAME SY
---------- ---------- --
John Brown 02
You cun get detus on the types delned by the user through the user_types vew. 1he
loowng query retreves the detus ol the type wth u typeid ol '02' (the ID returned by SYS_
TYPEID() eurer) und the type_name ol T_BUSINESS_PERSON:
SELECT typecode, attributes, methods, supertype_name
FROM user_types
WHERE typeid = '02'
AND type_name = 'T_BUSINESS_PERSON';
TYPECODE ATTRIBUTES METHODS SUPERTYPE_NAME
-------- ---------- ---------- --------------
OBJECT 8 1 T_PERSON
lrom the output ol ths query you cun see thut the supertype ol t_business_person s
t_person. Aso, t_business_person hus eght uttrbutes und one method.
NOT lNSTANTlABlf Objcct Typcs
You cun murk un obect type us NOT INSTANTIABLE, whch prevents obects ol thut type lrom
beng creuted. You mght wunt to murk un obect type us NOT INSTANTIABLE when you use the
type us un ubstruct supertype ony und never creute uny obects ol thut type. lor exumpe, you
coud creute u t_vehicle ubstruct type und use t us u supertype lor u t_car subtype und u t_
motorcycle subtype, you woud then creute uctuu t_car und t_motorcycle obects, but
never t_vehicle obects.
Chupter l2: Dutubuse Cbects

1he loowng stutement creutes u type numed t_vehicle, whch s murked us NOT
INSTANTIABLE:
CREATE TYPE t_vehicle AS OBJECT (
id INTEGER,
make VARCHAR2(15),
model VARCHAR2(15)
) NOT FINAL NOT INSTANTIABLE;
/

Thc t_vehicle |,pc ao mar|cd a NOT FINAL, bccauc a


NOT INSTANTIABLE |,pc canno| bc FINAL. | | were FINAL, ,ou
voudn'| bc abc |o uc | a a upcr|,pc, vhch |hc vhoc pon| o|
crca|ng | n |hc |r| pacc.
1he next exumpe creutes u subtype numed t_car under the t_vehicle supertype, notce
thut t_car hus un uddtonu uttrbute numed convertible, whch w be used to record
whether the cur hus u convertbe rool (Y lor yes, N lor no):
CREATE TYPE t_car UNDER t_vehicle (
convertible CHAR(1)
);
/
1he loowng exumpe creutes u subtype numed t_motorcycle under the t_vehicle
supertype, notce thut t_motorcycle hus un uddtonu uttrbute numed sidecar, whch w
be used to record whether the motorcyce hus u sdecur (Y lor yes, N lor no):
CREATE TYPE t_motorcycle UNDER t_vehicle (
sidecar CHAR(1)
);
/
1he next exumpe creutes tubes numed vehicles, cars, und motorcycles, whch ure
obect tubes ol the types t_vehicle, t_car, und t_motorcycle respectvey:
CREATE TABLE vehicles OF t_vehicle;
CREATE TABLE cars OF t_car;
CREATE TABLE motorcycles OF t_motorcycle;
ecuuse t_vehicle s NOT INSTANTIABLE, you cunnot udd un obect to the vehicles
tube. ll you uttempt to do so, the dutubuse returns un error:
SQL> INSERT INTO vehicles VALUES (
2 t_vehicle(1, 'Toyota', 'MR2', '01-FEB-1955')
3 );
t_vehicle(1, 'Toyota', 'MR2', '01-FEB-1955')
*
ERROR at line 2:
ORA-22826: cannot construct an instance of a non instantiable type
418
Cruce Dutubuse ll SQL
1he loowng exumpes udd obects to the cars und motorcycles tubes:
INSERT INTO cars VALUES (
t_car(1, 'Toyota', 'MR2', 'Y')
);
INSERT INTO motorcycles VALUES (
t_motorcycle(1, 'Harley-Davidson', 'V-Rod', 'N')
);
1he loowng queres retreve the obects lrom the cars und motorcycles tubes:
SELECT *
FROM cars;
ID MAKE MODEL C
---------- --------------- --------------- -
1 Toyota MR2 Y
SELECT *
FROM motorcycles;
ID MAKE MODEL S
---------- --------------- --------------- -
1 Harley-Davidson V-Rod N
Uscr-Dcfincd Cunstructurs
As n other obect-orented unguuges ke }uvu und Cr, you cun delne your own constructors
n lL/SQL to ntuze u new obect. You cun delne your own constructor to do such thngs us
progrummutcuy settng the uttrbutes ol u new obect to deluut vuues.
1he loowng exumpe creutes u type numed t_person2 thut decures two constructor
methods wth dllerng numbers ol purumeters:
CREATE TYPE t_person2 AS OBJECT (
id INTEGER,
first_name VARCHAR2(10),
last_name VARCHAR2(10),
dob DATE,
phone VARCHAR2(12),
CONSTRUCTOR FUNCTION t_person2(
p_id INTEGER,
p_first_name VARCHAR2,
p_last_name VARCHAR2
) RETURN SELF AS RESULT,
CONSTRUCTOR FUNCTION t_person2(
p_id INTEGER,
p_first_name VARCHAR2,
p_last_name VARCHAR2,
p_dob DATE
) RETURN SELF AS RESULT
);
/
Chupter l2: Dutubuse Cbects

Notce the loowng ubout the constructor decurutons:


1he CONSTRUCTOR FUNCTION keywords ure used to dently the constructors.
1he RETURN SELF AS RESULT keywords ndcute the current obect beng processed
s returned by euch constructor, SELF represents the current obect beng processed.
\hut ths meuns s thut the constructor returns the new obect t creutes.
1he lrst constructor uccepts three purumeters (p_id, p_first_name, und p_last_
name), und the second constructor uccepts lour purumeters (p_id, p_first_name,
p_last_name, und p_dob).
1he constructor decurutons don't contun the uctuu code delntons lor the constructors, the
delntons ure contuned n the type body, whch s creuted by the loowng stutement:
CREATE TYPE BODY t_person2 AS
CONSTRUCTOR FUNCTION t_person2(
p_id INTEGER,
p_first_name VARCHAR2,
p_last_name VARCHAR2
) RETURN SELF AS RESULT IS
BEGIN
SELF.id := p_id;
SELF.first_name := p_first_name;
SELF.last_name := p_last_name;
SELF.dob := SYSDATE;
SELF.phone := '555-1212';
RETURN;
END;
CONSTRUCTOR FUNCTION t_person2(
p_id INTEGER,
p_first_name VARCHAR2,
p_last_name VARCHAR2,
p_dob DATE
) RETURN SELF AS RESULT IS
BEGIN
SELF.id := p_id;
SELF.first_name := p_first_name;
SELF.last_name := p_last_name;
SELF.dob := p_dob;
SELF.phone := '555-1213';
RETURN;
END;
END;
/
Notce the loowng:
1he constructors use SELF to relerence the new obect beng creuted. lor exumpe,
SELF.id := p_id sets the id uttrbute ol the new obect to the vuue ol the p_id
purumeter pussed nto the constructor.

Cruce Dutubuse llg SQL
1he lrst constructor sets the id, first_name, und last_name uttrbutes to the p_id,
p_first_name, und p_last_name purumeter vuues pussed nto the constructor, the
dob uttrbute s set to the current dutetme returned by SYSDATE(), und the phone
uttrbute s set to 555-1212.
1he second constructor sets the id, first_name, last_name, und dob uttrbutes to
the p_id, p_first_name, p_last_name, und p_dob purumeter vuues pussed nto
the constructor, the remunng phone uttrbute s set to 555-1213.
Athough not shown, the dutubuse uutomutcuy provdes u deluut constructor thut uccepts
lve purumeters und sets euch uttrbute to the upproprute purumeter vuue pussed nto the
constructor. You' see un exumpe ol ths shorty.

Thc con|ruc|or hov an cxampc o| method overoudng, vhcrcb,


mc|hod o| |hc amc namc bu| d||crcn| paramc|cr arc dc|ncd n
|hc amc |,pc. A mc|hod ma, bc ovcroadcd b, provdng d||crcn|
numbers o| paramc|cr, types o| paramc|cr, or orderng o| paramc|cr.
1he loowng exumpe descrbes t_person2, notce the constructor delntons n the output:
DESCRIBE t_person2
Name Null? Type
----------------------------------------- -------- -------------------
ID NUMBER(38)
FIRST_NAME VARCHAR2(10)
LAST_NAME VARCHAR2(10)
DOB DATE
PHONE VARCHAR2(12)
METHOD
------
FINAL CONSTRUCTOR FUNCTION T_PERSON2 RETURNS SELF AS RESULT
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
P_ID NUMBER IN
P_FIRST_NAME VARCHAR2 IN
P_LAST_NAME VARCHAR2 IN
METHOD
------
FINAL CONSTRUCTOR FUNCTION T_PERSON2 RETURNS SELF AS RESULT
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
P_ID NUMBER IN
P_FIRST_NAME VARCHAR2 IN
P_LAST_NAME VARCHAR2 IN
P_DOB DATE IN
1he loowng stutement creutes u tube ol type t_person2:
Chupter l2: Dutubuse Cbects

CREATE TABLE object_customers2 OF t_person2;


1he loowng INSERT stutement udds un obect to the tube, notce thut three purumeters ure
pussed to the t_person2 constructor:
INSERT INTO object_customers2 VALUES (
t_person2(1, 'Jeff', 'Jones')
);
ecuuse three purumeters ure pussed to t_person2, ths INSERT stutement exercses the lrst
constructor. 1hs constructor sets the id, first_name, und last_name uttrbutes ol the new
obect to l, Jeff, und Jones, the remunng dob und phone uttrbutes ure set to the resut
returned by SYSDATE() und the teru 555-1212. 1he loowng query retreves the new obect:
SELECT *
FROM object_customers2
WHERE id = 1;
ID FIRST_NAME LAST_NAME DOB PHONE
---------- ---------- ---------- --------- --------
1 Jeff Jones 17-JUN-07 555-1212
1he next INSERT stutement udds unother obect to the tube, notce thut lour purumeters ure
pussed to the t_person2 constructor:
INSERT INTO object_customers2 VALUES (
t_person2(2, 'Gregory', 'Smith', '03-APR-1965')
);
ecuuse lour purumeters ure pussed to t_person2, ths INSERT stutement exercses the
second constructor. 1hs constructor sets the id, first_name, last_name, und dob uttrbutes
ol the obect to 2, Gregory, Smith, und 03-APR-1965, respectvey, the remunng phone
uttrbute s set to 555-1213. 1he loowng query retreves the new obect:
SELECT *
FROM object_customers2
WHERE id = 2;
ID FIRST_NAME LAST_NAME DOB PHONE
---------- ---------- ---------- --------- --------
2 Gregory Smith 03-APR-65 555-1213
1he next INSERT stutement udds unother obect to the tube, notce thut lve purumeters ure
pussed to the t_person2 constructor:
INSERT INTO object_customers2 VALUES (
t_person2(3, 'Jeremy', 'Hill', '05-JUN-1975', '555-1214')
);
ecuuse lve purumeters ure pussed to t_person2, ths INSERT stutement exercses the
deluut constructor. 1hs constructor sets the id, first_name, last_name, dob, und phone
422
Cruce Dutubuse ll SQL
uttrbutes to 3, Jeremy, Hill, 05-JUN-1975, und 555-1214, respectvey. 1he loowng
query retreves the new obect:
SELECT *
FROM object_customers2
WHERE id = 3;
ID FIRST_NAME LAST_NAME DOB PHONE
---------- ---------- ---------- --------- --------
3 Jeremy Hill 05-JUN-75 555-1214
Ovcrriding Mcthuds
\hen you creute u subtype under u supertype, you cun overrde u method n the supertype wth u
method n the subtype. 1hs gves you u very lexbe wuy ol delnng methods n u herurchy ol types.
1he loowng stutements creute u supertype numed t_person3, notce thut the display_
details() luncton returns u VARCHAR2 contunng the uttrbute vuues ol the obect:
CREATE TYPE t_person3 AS OBJECT (
id INTEGER,
first_name VARCHAR2(10),
last_name VARCHAR2(10),
MEMBER FUNCTION display_details RETURN VARCHAR2
) NOT FINAL;
/
CREATE TYPE BODY t_person3 AS
MEMBER FUNCTION display_details RETURN VARCHAR2 IS
BEGIN
RETURN 'id=' || id ||
', name=' || first_name || ' ' || last_name;
END;
END;
/
1he next set ol stutements creutes u subtype numed t_business_person3 under t_
person3, notce thut the display_details() luncton s overrdden usng the OVERRIDING
keyword und thut the luncton returns u VARCHAR2 contunng the orgnu und extended uttrbute
vuues ol the obect:
CREATE TYPE t_business_person3 UNDER t_person3 (
title VARCHAR2(20),
company VARCHAR2(20),
OVERRIDING MEMBER FUNCTION display_details RETURN VARCHAR2
);
/
CREATE TYPE BODY t_business_person3 AS
OVERRIDING MEMBER FUNCTION display_details RETURN VARCHAR2 IS
BEGIN
RETURN 'id=' || id ||
', name=' || first_name || ' ' || last_name ||
', title=' || title || ', company=' || company;
Chupter l2: Dutubuse Cbects
423
END;
END;
/
1he use ol the OVERRIDING keyword ndcutes thut display_details() n t_business_
person3 overrdes display_details() n t_person3, therelore, when display_details()
n t_business_person3 s cued, t cus display_details() n t_business_person3, not
display_details() n t_person3.
NOTf
n |hc ncx| cc|on o| |h chap|cr, ,ou' cc hov ,ou can drcc|, ca
a mc|hod n a upcr|,pc |rom a ub|,pc. Th avc ,ou |rom havng
|o rccrca|c codc n |hc ub|,pc |ha| arcad, n |hc upcr|,pc. You do
|h drcc| cang b, ung a ncv |ca|urc cacd generuzed nvocuton
n Cracc Da|abac 11g.
1he loowng stutements creute u tube numed object_business_customers3 und udd
un obect to ths tube:
CREATE TABLE object_business_customers3 OF t_business_person3;
INSERT INTO object_business_customers3 VALUES (
t_business_person3(1, 'John', 'Brown', 'Manager', 'XYZ Corp')
);
1he loowng exumpe cus display_details() usng object_business_customers3:
SELECT o.display_details()
FROM object_business_customers3 o
WHERE id = 1;
O.DISPLAY_DETAILS()
------------------------------------------------------
id=1, name=John Brown, title=Manager, company=XYZ Corp
ecuuse the display_details() luncton us delned n t_business_person3 s cued,
the VARCHAR2 returned by the luncton contuns the id, first_name, und last_name uttrbutes,
uong wth the title und company uttrbutes.
GcncraIizcd lnvucatiun
As you suw n the prevous secton, you cun overrde u method n the supertype wth u method n
the subtype. Ccncra2cd nvoca|on s u new leuture n Cruce Dutubuse llg und uows you to
cu u method n u supertype lrom u subtype. As you' see, generuzed nvocuton suves you lrom
huvng to recreute code n the subtype thut s ureudy n the supertype.
NOTf
'vc provdcd an S*u crp| namcd object_schema3.sql,
vhch crca|c a |hc |cm hovn n |hc rc| o| |h chap|cr. You can
run |hc object_schema3.sql crp| on, | ,ou arc ung Cracc
Da|abac 11g. A||cr |hc crp| compc|c, ,ou v bc oggcd n a
object_user3.

Cruce Dutubuse ll SQL
1he loowng stutements creute u supertype numed t_person, notce thut the display_
details() luncton returns u VARCHAR2 contunng the uttrbute vuues:
CREATE TYPE t_person AS OBJECT (
id INTEGER,
first_name VARCHAR2(10),
last_name VARCHAR2(10),
MEMBER FUNCTION display_details RETURN VARCHAR2
) NOT FINAL;
/
CREATE TYPE BODY t_person AS
MEMBER FUNCTION display_details RETURN VARCHAR2 IS
BEGIN
RETURN 'id=' || id ||
', name=' || first_name || ' ' || last_name;
END;
END;
/
1he next set ol stutements creutes u subtype numed t_business_person under t_person,
notce thut the display_details() luncton s overrdden usng the OVERRIDING keyword:
CREATE TYPE t_business_person UNDER t_person (
title VARCHAR2(20),
company VARCHAR2(20),
OVERRIDING MEMBER FUNCTION display_details RETURN VARCHAR2
);
/
CREATE TYPE BODY t_business_person AS
OVERRIDING MEMBER FUNCTION display_details RETURN VARCHAR2 IS
BEGIN
-- use generalized invocation to call display_details() in t_person
RETURN (SELF AS t_person).display_details ||
', title=' || title || ', company=' || company;
END;
END;
/
As you cun see, display_details() n t_business_person overrdes display_
details() n t_person. 1he loowng ne n display_details() uses generuzed
nvocuton to cu u method n u supertype lrom u subtype:
RETURN (SELF AS t_person).display_details ||
', title=' || title || ', company=' || company;
\hut (SELF AS t_person).display_details does s to treut un obect ol the current
type (whch s t_business_person) us un obect ol type t_person und then to cu display_
details() n t_person. So, when display_details() n t_business_person s cued,
t lrst cus display_details() n t_person (whch dspuys the id, first_name, und
Chupter l2: Dutubuse Cbects
42S
last_name uttrbute vuues), then dspuys the title und company uttrbute vuues. 1hs meunt l
ddn't huve to re-creute the code ureudy n t_person.display_details() n t_business_
person.display_details(), thereby suvng some work. ll you huve more compex methods
n your types, ths leuture cun suve u ot ol work und muke your code euser to muntun.
1he loowng stutements creute u tube numed object_business_customers und udd un
obect to ths tube:
CREATE TABLE object_business_customers OF t_business_person;
INSERT INTO object_business_customers VALUES (
t_business_person(1, 'John', 'Brown', 'Manager', 'XYZ Corp')
);
1he loowng query cus display_details() usng object_business_customers:
SELECT o.display_details()
FROM object_business_customers o;
O.DISPLAY_DETAILS()
--------------------------------------------------------------------
id=1, name=John Brown, dob=01-FEB-55, title=Manager, company=XYZ Corp
As you cun see, the id, name, und dute ol brth (dob) ure dspuyed (whch come lrom
display_details() n t_person), loowed by the title und company (whch come
lrom display_details() n t_business_person).
Summary
ln ths chupter, you eurned the loowng:
1he Cruce dutubuse uows you to creute obect types. An obect type s ke u cuss n
}uvu, C++, und Cr. An obect type muy contun uttrbutes und methods, you creute un
obect type usng the CREATE TYPE stutement.
You cun use un obect type to delne u coumn obect or un obect tube.
You cun use un obect relerence to uccess un ndvduu row n un obect tube. An obect
relerence s smur to u ponter n C++.
You cun creute und munpuute obects n SQL und lL/SQL.
\th the reeuse ol Cruce Dutubuse 9, you cun use obect type nhertunce. 1hs uows
you to delne herurches ol dutubuse types.
You cun use u subtype obect n puce ol u supertype obect, whch gves you greut
lexbty when storng und munpuutng reuted types. ll you wunt to prevent the use
ol u subtype obect n puce ol supertype obect, you cun murk un obect tube or obect
coumn us NOT SUBSTITUTABLE.
You cun use u number ol uselu lunctons wth obects, such us REF(), DEREF(),
VALUE(), IS OF(), SYS_TYPEID(), und TREAT().

Cruce Dutubuse ll SQL
You cun murk un obect type us NOT INSTANTIABLE, whch prevents obects ol thut type
lrom beng creuted. You' wunt to murk un obect type us NOT INSTANTIABLE when
you use thut type us un ubstruct supertype und never uctuuy creute obects ol thut type.
You cun delne your own constructors to do thngs ke progrummutcuy settng u deluut
lor uttrbutes ol un obect.
You cun overrde u method n u supertype wth u method n u subtype, gvng you u very
lexbe wuy ol delnng methods n u herurchy ol types.
You cun use the new Cruce Dutubuse ll generuzed nvocuton leuture to cu methods
n supertype lrom u subtype. Dong ths cun suve you u ot ol work und muke your code
euser to muntun.
ln the next chupter, you' eurn ubout coectons.
\IAI1II
1J
Coectons
427
428
Cruce Dutubuse llg SQL
n ths chupter, you w do the loowng:
Leurn ubout coectons
Leurn how to creute coecton types
Lse coecton types to delne coumns n tubes
Creute und munpuute coecton dutu n SQL und lL/SQL
Leurn how u coecton muy tsel contun embedded coectons (u muteve
coecton)
Lxumne the enhuncements to coectons thut were ntroduced n Cruce Dutubuse l0g
lntruducing CuIIcctiuns
Cruce Dutubuse 8 ntroduced two new dutubuse types, known us cocc|on, thut uow you to
store sets ol eements. Cruce Dutubuse 9 extended these leutures to ncude muteve coectons,
whch uow you to embed u coecton wthn unother coecton. Cruce Dutubuse l0g lurther
extended coectons to ncude ussocutve urruys und much more.
1here ure three types ol coectons:
Varrays A vurruy s smur to un urruy n }uvu, C++, und Cr. A vurruy stores un ordered
set ol eements, und euch eement hus un ndex thut records ts poston n the urruy.
Lements n u vurruy cun be modled ony us u whoe, not ndvduuy, ths meuns thut
even l you ony wunt to modly one eement, you must suppy u the eements lor the
vurruy. A vurruy hus u muxmum sze thut you set when creutng t, but you cun chunge
the sze uter.
Ncstcd tabIcs A nested tube s u tube thut s embedded wthn unother tube. You cun
nsert, updute, und deete ndvduu eements n u nested tube, ths mukes them more
lexbe thun u vurruy, whose eements cun be modled ony us u whoe. A nested tube
doesn't huve u muxmum sze, und you cun store un urbtrury number ol eements n u
nested tube.
Assuciativc arrays (furmcrIy knuwn as indcx-by tabIcs) An ussocutve urruy s smur
to u hush tube n }uvu. lntroduced n Cruce Dutubuse l0g, un ussocutve urruy s u set
ol key und vuue purs. You cun get the vuue lrom the urruy usng the key (whch muy be
u strng) or un nteger thut specles the poston ol the vuue n the urruy. An ussocutve
urruy cun be used ony n lL/SQL und cunnot be stored n the dutubuse.
You mght be uskng yoursel why you woud wunt to use coectons n the lrst puce. Alter
u, usng two tubes wth u loregn key ureudy uows you to mode reutonshps between dutu.
1he unswer s thut coectons loow the obect-orented stye ol modern progrummng, n uddton,
the dutu stored n the coecton muy be uccessed more rupdy by the dutubuse thun l you were
to use two reutonu tubes to store the sume dutu.

Chupter l3: Coectons


429
l've provded un SQL*lus scrpt numed collection_schema.sql n the SQL drectory. 1he
scrpt creutes u user numed collection_user wth u pussword ol collection_password,
und creutes the coecton types, tubes, und lL/SQL code used n the lrst purt ol ths chupter. You
must run ths scrpt whe ogged n us u user wth the requred prveges to creute u new user wth
the CONNECT und RESOURCE prveges, l og n us the system user on my dutubuse to run the
scrpts. Alter the scrpt competes, you w be ogged n us collection_user.
Crcating CuIIcctiun Typcs
ln ths secton, you' see how to creute u vurruy type und u nested tube type.
Crcating a Varray Typc
A vurruy stores un ordered set ol eements, u ol the sume type, und the type cun be u but-n
dutubuse type or u user-delned obect type. Luch eement hus un ndex thut corresponds to ts
poston n the urruy, und you cun modly eements n the vurruy ony us u whoe.
You creute u vurruy type usng the CREATE TYPE stutement, n whch you specly the
muxmum sze und the type ol eements stored n the vurruy. 1he loowng exumpe creutes
u type numed t_varray_address thut cun store up to three VARCHAR2 strngs:
CREATE TYPE t_varray_address AS VARRAY(3) OF VARCHAR2(50);
/
Luch VARCHAR2 w be used to represent u dllerent uddress lor u customer ol our exumpe store.
ln Cruce Dutubuse l0 und hgher, you cun chunge the muxmum number ol eements ol u
vurruy usng the ALTER TYPE stutement. lor exumpe, the loowng stutement uters the muxmum
number ol eements to ten:
ALTER TYPE t_varray_address MODIFY LIMIT 10 CASCADE;
1he CASCADE opton propugutes the chunge to uny dependent obects n the dutubuse.
Crcating a Ncstcd TabIc Typc
A nested tube stores un unordered set ol uny number ol eements. You cun nsert, updute, und
deete ndvduu eements n u nested tube. A nested tube doesn't huve u muxmum sze, und you
cun store un urbtrury number ol eements n u nested tube.
ln ths secton, you' see u nested tube type thut stores t_address obect types. You suw
the use ol t_address n the prevous chupter, t s used to represent un uddress und s delned
us loows:
CREATE TYPE t_address AS OBJECT (
street VARCHAR2(15),
city VARCHAR2(15),
state CHAR(2),
zip VARCHAR2(5)
);
/
You creute u nested tube type usng the CREATE TYPE stutement, und the loowng exumpe
creutes u type numed t_nested_table_address thut stores t_address obects:
CREATE TYPE t_nested_table_address AS TABLE OF t_address;
/
430
Cruce Dutubuse ll SQL
Notce thut you don't specly the muxmum sze ol u nested tube. 1hut's becuuse u nested
tube cun store uny number ol eements.
Using a CuIIcctiun Typc tu Dcfinc a CuIumn
in a TabIc
Cnce you've creuted u coecton type, you cun use t to delne u coumn n u tube. You' see
how to use the vurruy type und nested tube type creuted n the prevous secton to delne u
coumn n u tube.
Using a Varray Typc tu Dcfinc a CuIumn in a TabIc
1he loowng stutement creutes u tube numed customers_with_varray, whch uses
t_varray_address to delne u coumn numed addresses:
CREATE TABLE customers_with_varray (
id INTEGER PRIMARY KEY,
first_name VARCHAR2(10),
last_name VARCHAR2(10),
addresses t_varray_address
);
1he eements n u vurruy ure stored drecty nsde the tube when the sze ol the vurruy s 4K
or ess, otherwse, the vurruy s stored outsde ol the tube. \hen u vurruy s stored wth the tube,
uccessng ts eements s luster thun uccessng eements n u nested tube.
Using a Ncstcd TabIc Typc tu Dcfinc a CuIumn in a TabIc
1he loowng stutement creutes u tube numed customers_with_nested_table, whch uses
t_nested_table_address to delne u coumn numed addresses:
CREATE TABLE customers_with_nested_table (
id INTEGER PRIMARY KEY,
first_name VARCHAR2(10),
last_name VARCHAR2(10),
addresses t_nested_table_address
)
NESTED TABLE
addresses
STORE AS
nested_addresses;
1he NESTED TABLE cuuse dentles the nume ol the nested tube coumn (addresses
n the exumpe), und the STORE AS cuuse specles the nume ol the nested tube (nested_
addresses n the exumpe) where the uctuu eements ure stored. You cunnot uccess the nested
tube ndependenty ol the tube n whch t s embedded.
Chupter l3: Coectons
431
Gctting lnfurmatiun un CuIIcctiuns
As you' see n ths secton, you cun use the DESCRIBE commund und u coupe ol user vews to
get nlormuton on your coectons.
Gctting lnfurmatiun un a Varray
1he loowng exumpe descrbes t_varray_address:
DESCRIBE t_varray_address
t_varray_address VARRAY(3) OF VARCHAR2(50)
1he next exumpe descrbes the customers_with_varray tube, whose addresses
coumn s ol the t_varray_address type:
DESCRIBE customers_with_varray
Name Null? Type
------------------------------- -------- ------------------
ID NOT NULL NUMBER(38)
FIRST_NAME VARCHAR2(10)
LAST_NAME VARCHAR2(10)
ADDRESSES T_VARRAY_ADDRESS
You cun uso get nlormuton on your vurruys lrom the user_varrays vew. 1ube l3-l
descrbes the coumns n user_varrays.
CuIumn Typc Dcscriptiun
parent_table_name VARCHAR2(30)
Nume ol the tube thut contuns the
vurruy.
parent_table_column VARCHAR2(4000)
Nume ol the coumn n the purent
tube contunng the vurruy.
type_owner VARCHAR2(30)
Lser who owns the vurruy type.
type_name VARCHAR2(30)
Nume ol the vurruy type.
lob_name VARCHAR2(30)
Nume ol the urge obect (LC) when
the vurruy s stored n un LC. You'
eurn ubout LCs n the next chupter.
storage_spec VARCHAR2(30)
Storuge speclcuton lor the vurruy.
return_type VARCHAR2(20)
Return type ol the coumn.
element_
substitutable
VARCHAR2(25)
\hether or not (Y/N) the vurruy
eement s substtutube lor u subtype.
TABlf 13-1 Coumn n |hc user_varrays Vcv
432
Cruce Dutubuse llg SQL
NOTf
You can gc| n|orma|on on a |hc varra, ,ou havc accc |o ung |hc
all_varrays vcv.
1he loowng exumpe retreves the detus lor t_varray_address lrom user_varrays:
SELECT parent_table_name, parent_table_column, type_name
FROM user_varrays
WHERE type_name = 'T_VARRAY_ADDRESS';
PARENT_TABLE_NAME
---------------------
PARENT_TABLE_COLUMN
---------------------
TYPE_NAME
---------------------
CUSTOMERS_WITH_VARRAY
ADDRESSES
T_VARRAY_ADDRESS
Gctting lnfurmatiun un a Ncstcd TabIc
You cun uso use DESCRIBE wth u nested tube, us shown n the loowng exumpe thut
descrbes t_nested_table_address:
DESCRIBE t_nested_table_address
t_nested_table_address TABLE OF T_ADDRESS
Name Null? Type
----------------------------------------- -------- ------------
STREET VARCHAR2(15)
CITY VARCHAR2(15)
STATE CHAR(2)
ZIP VARCHAR2(5)
1he next exumpe descrbes the customers_with_nested_table tube, whose
addresses coumn s ol type t_nested_table_address:
DESCRIBE customers_with_nested_table
Name Null? Type
---------------------------------- -------- ----------------------
ID NOT NULL NUMBER(38)
FIRST_NAME VARCHAR2(10)
LAST_NAME VARCHAR2(10)
ADDRESSES T_NESTED_TABLE_ADDRESS
ll you set the depth to 2 und descrbe customers_with_nested_table, you cun see the
uttrbutes thut muke up t_nested_table_address:
SET DESCRIBE DEPTH 2
DESCRIBE customers_with_nested_table
Name Null? Type
----------------------------------- -------- -------------
ID NOT NULL NUMBER(38)
FIRST_NAME VARCHAR2(10)
Chupter l3: Coectons
433
LAST_NAME VARCHAR2(10)
ADDRESSES T_NESTED_TABLE_ADDRESS
STREET VARCHAR2(15)
CITY VARCHAR2(15)
STATE CHAR(2)
ZIP VARCHAR2(5)
You cun uso get nlormuton on your nested tubes lrom the user_nested_tables vew.
1ube l3-2 descrbes the coumns n user_nested_tables.
NOTf
You can gc| n|orma|on on a |hc nc|cd |abc ,ou havc accc |o
ung |hc all_nested_tables vcv.
1he loowng exumpe retreves the detus lor the nested_addresses tube lrom user_
nested_tables:
SELECT table_name, table_type_name, parent_table_name, parent_table_column
FROM user_nested_tables
WHERE table_name = 'NESTED_ADDRESSES';
TABLE_NAME TABLE_TYPE_NAME
------------------------------ ----------------------
PARENT_TABLE_NAME
------------------------------
PARENT_TABLE_COLUMN
-----------------------------------------------------
NESTED_ADDRESSES T_NESTED_TABLE_ADDRESS
CUSTOMERS_WITH_NESTED_TABLE
ADDRESSES
CuIumn Typc Dcscriptiun
table_name VARCHAR2(30)
Nume ol the nested tube
table_type_owner VARCHAR2(30)
Lser who owns the nested tube type
table_type_name VARCHAR2(30)
Nume ol the nested tube type
parent_table_name VARCHAR2(30)
Nume ol the purent tube thut
contuns the nested tube
parent_table_column VARCHAR2(4000)
Nume ol the coumn n the purent
tube contunng the nested tube
storage_spec VARCHAR2(30)
Storuge speclcuton lor the nested
tube
return_type VARCHAR2(20)
Return type ol the coumn
element_substitutable VARCHAR2(25)
\hether or not (Y/N) the nested
tube eement s substtutube lor u
subtype.
TABlf 13-2 Coumn n |hc user_nested_tables Vcv
434
Cruce Dutubuse ll SQL
PupuIating a CuIIcctiun with fIcmcnts
ln ths secton, you' see how to popuute u vurruy und u nested tube wth eements usng INSERT
stutements. You don't huve to run the INSERT stutements shown n ths secton: they ure executed
when you run the collection_schema.sql scrpt.
PupuIating a Varray with fIcmcnts
1he loowng INSERT stutements udd rows to the customers_with_varray tube, notce the
use ol the t_varray_address constructor to specly the strngs lor the eements ol the vurruy:
INSERT INTO customers_with_varray VALUES (
1, 'Steve', 'Brown',
t_varray_address(
'2 State Street, Beantown, MA, 12345',
'4 Hill Street, Lost Town, CA, 54321'
)
);
INSERT INTO customers_with_varray VALUES (
2, 'John', 'Smith',
t_varray_address(
'1 High Street, Newtown, CA, 12347',
'3 New Street, Anytown, MI, 54323',
'7 Market Street, Main Town, MA, 54323'
)
);
As you cun see, the lrst row hus two uddresses und the second hus three. Any number ol
uddresses up to the muxmum mt lor the vurruy cun be stored.
PupuIating a Ncstcd TabIc with fIcmcnts
1he loowng INSERT stutements udd rows to customers_with_nested_table, notce the
use ol the t_nested_table_address und t_address constructors to specly the eements ol
the nested tube:
INSERT INTO customers_with_nested_table VALUES (
1, 'Steve', 'Brown',
t_nested_table_address(
t_address('2 State Street', 'Beantown', 'MA', '12345'),
t_address('4 Hill Street', 'Lost Town', 'CA', '54321')
)
);
INSERT INTO customers_with_nested_table VALUES (
2, 'John', 'Smith',
t_nested_table_address(
Chupter l3: Coectons
43S
t_address('1 High Street', 'Newtown', 'CA', '12347'),
t_address('3 New Street', 'Anytown', 'MI', '54323'),
t_address('7 Market Street', 'Main Town', 'MA', '54323')
)
);
As you cun see, the lrst row hus two uddresses und the second hus three. Any number ol
uddresses cun be stored n u nested tube.
Rctricving fIcmcnts frum CuIIcctiuns
ln ths secton, you' see how to retreve eements lrom u vurruy und u nested tube usng queres.
1he output lrom the queres hus been lormutted sghty to muke the resuts more reudube.
Rctricving fIcmcnts frum a Varray
1he loowng query retreves customer rl lrom the customers_with_varray tube, one row
s returned, und t contuns the two uddresses stored n the vurruy:
SELECT *
FROM customers_with_varray
WHERE id = 1;
ID FIRST_NAME LAST_NAME
---------- ---------- ----------
ADDRESSES
-------------------------------------------------------
1 Steve Brown
T_VARRAY_ADDRESS('2 State Street, Beantown, MA, 12345',
'4 Hill Street, Lost Town, CA, 54321')
1he next query specles the uctuu coumn numes:
SELECT id, first_name, last_name, addresses
FROM customers_with_varray
WHERE id = 1;
ID FIRST_NAME LAST_NAME
---------- ---------- ----------
ADDRESSES
-------------------------------------------------------
1 Steve Brown
T_VARRAY_ADDRESS('2 State Street, Beantown, MA, 12345',
'4 Hill Street, Lost Town, CA, 54321')
1hese exumpes u return the uddresses n the vurruy us u snge row. Luter, n the secton
Lsng 1ALL() to 1reut u Coecton us u Seres ol Rows, you' see how you cun treut the dutu
stored n u coecton us u seres ol rows.
436
Cruce Dutubuse ll SQL
Rctricving fIcmcnts frum a Ncstcd TabIc
1he loowng query retreves customer rl lrom customers_with_nested_table, one row s
returned, und t contuns the two uddresses stored n the nested tube:
SELECT *
FROM customers_with_nested_table
WHERE id = 1;
ID FIRST_NAME LAST_NAME
---------- ---------- ----------
ADDRESSES(STREET, CITY, STATE, ZIP)
--------------------------------------------------------
1 Steve Brown
T_NESTED_TABLE_ADDRESS(
T_ADDRESS('2 State Street', 'Beantown', 'MA', '12345'),
T_ADDRESS('4 Hill Street', 'Lost Town', 'CA', '54321'))
1he next query specles the uctuu coumn numes:
SELECT id, first_name, last_name, addresses
FROM customers_with_nested_table
WHERE id = 1;
ID FIRST_NAME LAST_NAME
---------- ---------- ----------
ADDRESSES(STREET, CITY, STATE, ZIP)
--------------------------------------------------------
1 Steve Brown
T_NESTED_TABLE_ADDRESS(
T_ADDRESS('2 State Street', 'Beantown', 'MA', '12345'),
T_ADDRESS('4 Hill Street', 'Lost Town', 'CA', '54321'))
1he next query gets ust the addresses nested tube, us n the prevous exumpes, one row s
returned, und t contuns the two uddresses stored n the nested tube:
SELECT addresses
FROM customers_with_nested_table
WHERE id = 1;

ADDRESSES(STREET, CITY, STATE, ZIP)
--------------------------------------------------------
T_NESTED_TABLE_ADDRESS(
T_ADDRESS('2 State Street', 'Beantown', 'MA', '12345'),
T_ADDRESS('4 Hill Street', 'Lost Town', 'CA', '54321'))
Using TABlf() tu Trcat a CuIIcctiun
as a Scrics uf Ruws
1he prevous queres you've seen n ths chupter return the contents ol u coecton us u snge
row. Sometmes, you muy wsh to treut the dutu stored n u coecton us u seres ol rows, lor
Chupter l3: Coectons
437
exumpe, you mght be workng wth u egucy uppcuton thut cun ony use rows. 1o treut u
coecton us u seres ol rows, you use the TABLE() luncton. ln ths secton, you' see how
to use TABLE() wth u vurruy und u nested tube.
Using TABlf() with a Varray
1he loowng query uses TABLE() to retreve customer rl's two uddresses lrom the
customers_with_varray tube, two sepurute rows ure returned:
SELECT a.*
FROM customers_with_varray c, TABLE(c.addresses) a
WHERE id = 1;
COLUMN_VALUE
-----------------------------------
2 State Street, Beantown, MA, 12345
4 Hill Street, Lost Town, CA, 54321
Notce how the Cruce dutubuse soltwure uutomutcuy udds the coumn nume ol COLUMN_
VALUE to the rows returned by the query. COLUMN_VALUE s u pseudo coumn uus, und t s
uutomutcuy udded when u coecton contuns dutu ol one ol the but-n dutu types, ke
VARCHAR2, CHAR, NUMBER, or DATE. ecuuse the exumpe vurruy contuns VARCHAR2 dutu, the
COLUMN_VALUE uus s udded. ll the vurruy hud contuned dutu ol u user-delned obect type,
then TABLE() woud return obects ol thut type und COLUMN_VALUE woud not uppeur, you'
see un exumpe ol ths n the next secton.
You cun uso embed un entre SELECT stutement nsde TABLE(). lor exumpe, the loowng
query rewrtes the prevous exumpe, pucng u SELECT nsde TABLE():
SELECT *
FROM TABLE(
-- get the addresses for customer #1
SELECT addresses
FROM customers_with_varray
WHERE id = 1
);
COLUMN_VALUE
-----------------------------------
2 State Street, Beantown, MA, 12345
4 Hill Street, Lost Town, CA, 54321
1he loowng query shows unother exumpe thut uses TABLE() to get the uddresses:
SELECT c.id, c.first_name, c.last_name, a.*
FROM customers_with_varray c, TABLE(c.addresses) a
WHERE id = 1;
ID FIRST_NAME LAST_NAME
---------- ---------- ----------
COLUMN_VALUE
-----------------------------------
1 Steve Brown
438
Cruce Dutubuse ll SQL
2 State Street, Beantown, MA, 12345
1 Steve Brown
4 Hill Street, Lost Town, CA, 54321
Using TABlf() with a Ncstcd TabIc
1he loowng query uses TABLE() to retreve customer rl's two uddresses lrom customers_
with_nested_table, notce thut two sepurute rows ure returned:
SELECT a.*
FROM customers_with_nested_table c, TABLE(c.addresses) a
WHERE id = 1;
STREET CITY ST ZIP
--------------- --------------- -- -----
2 State Street Beantown MA 12345
4 Hill Street Lost Town CA 54321
1he next query gets the street und state uttrbutes ol the uddresses:
SELECT a.street, a.state
FROM customers_with_nested_table c, TABLE(c.addresses) a
WHERE id = 1;
STREET ST
--------------- --
2 State Street MA
4 Hill Street CA
1he loowng query shows unother exumpe thut uses TABLE() to get the uddresses:
SELECT c.id, c.first_name, c.last_name, a.*
FROM customers_with_nested_table c, TABLE(c.addresses) a
WHERE c.id = 1;
ID FIRST_NAME LAST_NAME STREET CITY ST ZIP
------ ---------- ---------- --------------- -------------- -- -----
1 Steve Brown 2 State Street Beantown MA 12345
1 Steve Brown 4 Hill Street Lost Town CA 54321
You' see un mportunt use ol TABLE() uter n the secton Modlyng Lements ol u
Nested 1ube.
Mudifying fIcmcnts uf CuIIcctiuns
ln ths secton, you' see how to modly the eements n u vurruy und u nested tube. You shoud
lee lree to run the UPDATE, INSERT, und DELETE stutements shown n ths secton.
Mudifying fIcmcnts uf a Varray
1he eements n u vurruy cun be modled ony us u whoe, whch meuns thut even l you ony wunt
to modly one eement, you must suppy u the eements lor the vurruy. 1he loowng UPDATE
stutement modles the uddresses ol customer r2 n the customers_with_varray tube:
Chupter l3: Coectons
439
UPDATE customers_with_varray
SET addresses = t_varray_address(
'6 Any Street, Lost Town, GA, 33347',
'3 New Street, Anytown, MI, 54323',
'7 Market Street, Main Town, MA, 54323'
)
WHERE id = 2;
1 row updated.
Mudifying fIcmcnts uf a Ncstcd TabIc
Lnke n u vurruy, eements n u nested tube cun be modled ndvduuy. You cun nsert, updute,
und deete ndvduu eements n u nested tube, you' see how to do u three ol these modlcutons
n ths secton.
1he loowng INSERT stutement udds un uddress to customer r2 n customer_with_
nested_table, notce thut TABLE() s used to get the uddresses us u seres ol rows:
INSERT INTO TABLE(
-- get the addresses for customer #2
SELECT addresses
FROM customers_with_nested_table
WHERE id = 2
) VALUES (
t_address('5 Main Street', 'Uptown', 'NY', '55512')
);
1 row created.
1he loowng UPDATE stutement chunges the '1 High Street'uddress ol customer r2 to
'9 Any Street', notce the use ol the uus addr n the VALUE cuuses when speclyng the
uddresses:
UPDATE TABLE(
-- get the addresses for customer #2
SELECT addresses
FROM customers_with_nested_table
WHERE id = 2
) addr
SET VALUE(addr) =
t_address('9 Any Street', 'Lost Town', 'VA', '74321')
WHERE VALUE(addr) =
t_address('1 High Street', 'Newtown', 'CA', '12347');
1 row updated.
1he loowng DELETE stutement removes the '3 New Street...' uddress lrom
customer r2:
DELETE FROM TABLE(
-- get the addresses for customer #2
SELECT addresses
FROM customers_with_nested_table
440
Cruce Dutubuse ll SQL
WHERE id = 2
) addr
WHERE VALUE(addr) =
t_address('3 New Street', 'Anytown', 'MI', '54323');
1 row deleted.
Using a Map Mcthud tu Cumparc thc Cuntcnts uf
Ncstcd TabIcs
You cun compure the contents ol one nested tube wth the contents ol unother. 1wo nested tubes
ure equu ony l
1hey ure ol the sume type.
1hey huve the sume number ol rows.
A ther eements contun the sume vuues.
ll the eements ol the nested tube ure ol u but-n dutubuse type, ke NUMBER, VARCHAR2,
und so on, then the dutubuse w uutomutcuy compure the contents ol the nested tubes lor you.
ll, however, the eements ure ol u user-delned obect type, then you w need to provde u mup
luncton thut contuns code to compure the obects (mup lunctons were shown n the secton
Compurng Cbect Vuues ol the prevous chupter).
1he loowng stutements creute u type numed t_address2 thut contuns u mup luncton
numed get_string(), notce thut get_string() returns u VARCHAR2 contunng the vuues
lor the zip, state, city, und street uttrbutes:
CREATE TYPE t_address2 AS OBJECT (
street VARCHAR2(15),
city VARCHAR2(15),
state CHAR(2),
zip VARCHAR2(5),
-- declare the get_string() map function,
-- which returns a VARCHAR2 string
MAP MEMBER FUNCTION get_string RETURN VARCHAR2
);
/
CREATE TYPE BODY t_address2 AS
-- define the get_string() map function
MAP MEMBER FUNCTION get_string RETURN VARCHAR2 IS
BEGIN
-- return a concatenated string containing the
-- zip, state, city, and street attributes
RETURN zip || ' ' || state || ' ' || city || ' ' || street;
END get_string;
END;
/
Chupter l3: Coectons

As you' see shorty, the dutubuse w uutomutcuy cu get_string() when compurng


t_address2 obects.
1he loowng stutements creute u nested tube type und u tube, und udd u row to the tube:
CREATE TYPE t_nested_table_address2 AS TABLE OF t_address2;
/
CREATE TABLE customers_with_nested_table2 (
id INTEGER PRIMARY KEY,
first_name VARCHAR2(10),
last_name VARCHAR2(10),
addresses t_nested_table_address2
)
NESTED TABLE
addresses
STORE AS
nested_addresses2;
INSERT INTO customers_with_nested_table2 VALUES (
1, 'Steve', 'Brown',
t_nested_table_address2(
t_address2('2 State Street', 'Beantown', 'MA', '12345'),
t_address2('4 Hill Street', 'Lost Town', 'CA', '54321')
)
);
1he loowng query ncudes u nested tube n the WHERE cuuse, notce thut the uddresses
ulter the = n the WHERE cuuse ure the sume us those n the prevous INSERT stutement:
SELECT cn.id, cn.first_name, cn.last_name
FROM customers_with_nested_table2 cn
WHERE cn.addresses =
t_nested_table_address2(
t_address2('2 State Street', 'Beantown', 'MA', '12345'),
t_address2('4 Hill Street', 'Lost Town', 'CA', '54321')
);
ID FIRST_NAME LAST_NAME
---------- ---------- ----------
1 Steve Brown
\hen the query s executed, the dutubuse uutomutcuy cus get_string() to compure
the t_address2 obects n cn.addresses to the t_address2 obects ulter the = n the
WHERE cuuse. 1he get_string() luncton returns u VARCHAR2 strng contunng the zip,
state, city, und street uttrbutes ol the obects, und when the strngs ure equu lor every
obect, the nested tubes ure uso equu.
1he next query returns no rows becuuse the snge uddress ulter the = n the WHERE cuuse
mutches ony one ol the uddresses n cn.addresses (remember: two nested tubes ure equu
ony l they ure ol the sume type, havc |hc amc numbcr o| rov, und ther eements contun the
sume vuues):
SELECT cn.id, cn.first_name, cn.last_name
FROM customers_with_nested_table2 cn

Cruce Dutubuse llg SQL
WHERE cn.addresses =
t_nested_table_address2(
t_address2('4 Hill Street', 'Lost Town', 'CA', '54321')
);
no rows selected
ln Cruce Dutubuse l0g und hgher, you cun use the SUBMULTISET operutor to check
whether the contents ol one nested tube ure u subset ol unother nested tube. 1he loowng
query rewrtes the prevous exumpe und returns u row:
SELECT cn.id, cn.first_name, cn.last_name
FROM customers_with_nested_table2 cn
WHERE
t_nested_table_address2(
t_address2('4 Hill Street', 'Lost Town', 'CA', '54321')
)
SUBMULTISET OF cn.addresses;
ID FIRST_NAME LAST_NAME
---------- ---------- ----------
1 Steve Brown
ecuuse the uddress n the lrst purt ol the WHERE cuuse s u subset ol the uddresses n
cn.addresses, u mutch s lound und u row s returned.
1he loowng query shows unother exumpe, ths tme the uddresses n cn.addresses
ure u subset ol the uddresses ulter OF n the WHERE cuuse:
SELECT cn.id, cn.first_name, cn.last_name
FROM customers_with_nested_table2 cn
WHERE
cn.addresses SUBMULTISET OF
t_nested_table_address2(
t_address2('2 State Street', 'Beantown', 'MA', '12345'),
t_address2('4 Hill Street', 'Lost Town', 'CA', '54321'),
t_address2('6 State Street', 'Beantown', 'MA', '12345')
);
ID FIRST_NAME LAST_NAME
---------- ---------- ----------
1 Steve Brown
You' eurn more ubout the SUBMULTISET operutor uter n ths chupter n the secton
SLMLL1lSL1 Cperutor. Aso, n the secton Lquu und Not-Lquu Cperutors, you' see
how to use the ANSl operutors mpemented n Cruce Dutubuse l0g to compure nested tubes.

Thcrc no drcc| mcchanm |or comparng |hc con|cn| o| varra,.


Chupter l3: Coectons
443
Using CAST() tu Cunvcrt CuIIcctiuns frum Onc
Typc tu Anuthcr
You muy use CAST() to convert u coecton ol one type to unother coecton type. ln ths
secton, you' see how to use CAST() to convert u vurruy to u nested tube und vce versu.
Using CAST() tu Cunvcrt a Varray tu a Ncstcd TabIc
1he loowng stutements creute und popuute u tube numed customers_with_varray2 thut
contuns un addresses coumn ol type t_varray_address2:
CREATE TYPE t_varray_address2 AS VARRAY(3) OF t_address;
/
CREATE TABLE customers_with_varray2 (
id INTEGER PRIMARY KEY,
first_name VARCHAR2(10),
last_name VARCHAR2(10),
addresses t_varray_address2
);
INSERT INTO customers_with_varray2 VALUES (
1, 'Jason', 'Bond',
t_varray_address2(
t_address('9 Newton Drive', 'Sometown', 'WY', '22123'),
t_address('6 Spring Street', 'New City', 'CA', '77712')
)
);
1he loowng query uses CAST() to return the vurruy uddresses lor customer rl us u nested
tube, notce thut the uddresses uppeur n u constructor lor the T_NESTED_TABLE_ADDRESS type,
ndcutng the converson ol the eements to ths type:
SELECT CAST(cv.addresses AS t_nested_table_address)
FROM customers_with_varray2 cv
WHERE cv.id = 1;
CAST(CV.ADDRESSESAST_NESTED_TABLE_ADDRESS)(STREET, CITY, STATE, ZIP)
--------------------------------------------------------------------
T_NESTED_TABLE_ADDRESS(
T_ADDRESS('9 Newton Drive', 'Sometown', 'WY', '22123'),
T_ADDRESS('6 Spring Street', 'New City', 'CA', '77712'))
Using CAST() tu Cunvcrt a Ncstcd TabIc tu a Varray
1he loowng query uses CAST() to return the uddresses lor customer rl n customers_with_
nested_table us u vurruy, notce thut the uddresses uppeur n u constructor lor T_VARRAY_
ADDRESS2:
SELECT CAST(cn.addresses AS t_varray_address2)
FROM customers_with_nested_table cn
444
Cruce Dutubuse ll SQL
WHERE cn.id = 1;
CAST(CN.ADDRESSESAST_VARRAY_ADDRESS2)(STREET, CITY, STATE, ZIP)
---------------------------------------------------------------
T_VARRAY_ADDRESS2(
T_ADDRESS('2 State Street', 'Beantown', 'MA', '12345'),
T_ADDRESS('4 Hill Street', 'Lost Town', 'CA', '54321'))
Using CuIIcctiuns in Pl/SQl
You cun use coectons n lL/SQL. ln ths secton, you' see how to perlorm the loowng tusks
n lL/SQL:
Munpuute u vurruy
Munpuute u nested tube
Lse the lL/SQL coecton methods to uccess und munpuute coectons
A the puckuges you' see n ths secton ure creuted when you run the collection_
schema.sql scrpt. ll you perlormed uny ol the INSERT, UPDATE, or DELETE stutements
shown n the eurer sectons ol ths chupter, go uheud und rerun the collection_schema.sql
scrpt so thut your output mutches mne n ths secton.
ManipuIating a Varray
ln ths secton, you' see u puckuge numed varray_package, ths puckuge contuns the
loowng tems:
A REF CURSOR type numed t_ref_cursor
A luncton numed get_customers(), whch returns u t_ref_cursor obect thut
ponts to the rows n the customers_with_varray tube
A procedure numed insert_customer(), whch udds u row to the customers_
with_varray tube
1he collection_schema.sql scrpt contuns the loowng puckuge speclcuton und
body lor varray_package:
CREATE PACKAGE varray_package AS
TYPE t_ref_cursor IS REF CURSOR;
FUNCTION get_customers RETURN t_ref_cursor;
PROCEDURE insert_customer(
p_id IN customers_with_varray.id%TYPE,
p_first_name IN customers_with_varray.first_name%TYPE,
p_last_name IN customers_with_varray.last_name%TYPE,
p_addresses IN customers_with_varray.addresses%TYPE
);
END varray_package;
/
Chupter l3: Coectons

CREATE PACKAGE BODY varray_package AS


-- get_customers() function returns a REF CURSOR
-- that points to the rows in customers_with_varray
FUNCTION get_customers
RETURN t_ref_cursor IS
--declare the REF CURSOR object
v_customers_ref_cursor t_ref_cursor;
BEGIN
-- get the REF CURSOR
OPEN v_customers_ref_cursor FOR
SELECT *
FROM customers_with_varray;
-- return the REF CURSOR
RETURN customers_ref_cursor;
END get_customers;
-- insert_customer() procedure adds a row to
-- customers_with_varray
PROCEDURE insert_customer(
p_id IN customers_with_varray.id%TYPE,
p_first_name IN customers_with_varray.first_name%TYPE,
p_last_name IN customers_with_varray.last_name%TYPE,
p_addresses IN customers_with_varray.addresses%TYPE
) IS
BEGIN
INSERT INTO customers_with_varray
VALUES (p_id, p_first_name, p_last_name, p_addresses);
COMMIT;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
END insert_customer;
END varray_package;
/
1he loowng exumpe cus insert_customer() to udd u new row to the customers_
with_varray tube:
CALL varray_package.insert_customer(
3, 'James', 'Red',
t_varray_address(
'10 Main Street, Green Town, CA, 22212',
'20 State Street, Blue Town, FL, 22213'
)
);
Call completed.
1he next exumpe cus get_products() to retreve the rows lrom customers_with_
varray:
446
Cruce Dutubuse ll SQL
SELECT varray_package.get_customers
FROM dual;
GET_CUSTOMERS
--------------------
CURSOR STATEMENT : 1
CURSOR STATEMENT : 1
ID FIRST_NAME LAST_NAME
---------- ---------- ----------
ADDRESSES
---------------------------------------------------------
1 Steve Brown
T_VARRAY_ADDRESS('2 State Street, Beantown, MA, 12345',
'4 Hill Street, Lost Town, CA, 54321')
2 John Smith
T_VARRAY_ADDRESS('1 High Street, Newtown, CA, 12347',
'3 New Street, Anytown, MI, 54323',
'7 Market Street, Main Town, MA, 54323')
3 James Red
T_VARRAY_ADDRESS('10 Main Street, Green Town, CA, 22212',
'20 State Street, Blue Town, FL, 22213')
ManipuIating a Ncstcd TabIc
ln ths secton, you' see u puckuge numed nested_table_package, ths puckuge contuns the
loowng tems:
A REF CURSOR type numed t_ref_cursor
A luncton numed get_customers(), whch returns u t_ref_cursor obect thut
ponts to the rows n customers_with_nested_table
A procedure numed insert_customer(), whch udds u row to customers_with_
nested_table
1he collection_schema.sql scrpt contuns the loowng puckuge speclcuton und
body lor nested_table_package:
CREATE PACKAGE nested_table_package AS
TYPE t_ref_cursor IS REF CURSOR;
FUNCTION get_customers RETURN t_ref_cursor;
PROCEDURE insert_customer(
p_id IN customers_with_nested_table.id%TYPE,
p_first_name IN customers_with_nested_table.first_name%TYPE,
p_last_name IN customers_with_nested_table.last_name%TYPE,
p_addresses IN customers_with_nested_table.addresses%TYPE
);
Chupter l3: Coectons

END nested_table_package;
/
CREATE PACKAGE BODY nested_table_package AS
-- get_customers() function returns a REF CURSOR
-- that points to the rows in customers_with_nested_table
FUNCTION get_customers
RETURN t_ref_cursor IS
-- declare the REF CURSOR object
v_customers_ref_cursor t_ref_cursor;
BEGIN
-- get the REF CURSOR
OPEN v_customers_ref_cursor FOR
SELECT *
FROM customers_with_nested_table;
-- return the REF CURSOR
RETURN customers_ref_cursor;
END get_customers;
-- insert_customer() procedure adds a row to
-- customers_with_nested_table
PROCEDURE insert_customer(
p_id IN customers_with_nested_table.id%TYPE,
p_first_name IN customers_with_nested_table.first_name%TYPE,
p_last_name IN customers_with_nested_table.last_name%TYPE,
p_addresses IN customers_with_nested_table.addresses%TYPE
) IS
BEGIN
INSERT INTO customers_with_nested_table
VALUES (p_id, p_first_name, p_last_name, p_addresses);
COMMIT;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
END insert_customer;
END nested_table_package;
/
1he loowng exumpe cus insert_customer() to udd u new row to customers_
with_nested_table:
CALL nested_table_package.insert_customer(
3, 'James', 'Red',
t_nested_table_address(
t_address('10 Main Street', 'Green Town', 'CA', '22212'),
t_address('20 State Street', 'Blue Town', 'FL', '22213')
)
);
Call completed.
448
Cruce Dutubuse ll SQL
1he next exumpe cus get_customers() to retreve the rows lrom customers_with_
nested_table:
SELECT nested_table_package.get_customers
FROM dual;
GET_CUSTOMERS
--------------------
CURSOR STATEMENT : 1
CURSOR STATEMENT : 1
ID FIRST_NAME LAST_NAME
---------- ---------- ----------
ADDRESSES(STREET, CITY, STATE, ZIP)
------------------------------------------------------------
1 Steve Brown
T_NESTED_TABLE_ADDRESS(
T_ADDRESS('2 State Street', 'Beantown', 'MA', '12345'),
T_ADDRESS('4 Hill Street', 'Lost Town', 'CA', '54321'))
2 John Smith
T_NESTED_TABLE_ADDRESS(
T_ADDRESS('1 High Street', 'Newtown', 'CA', '12347'),
T_ADDRESS('3 New Street', 'Anytown', 'MI', '54323'),
T_ADDRESS('7 Market Street', 'Main Town', 'MA', '54323'))
3 James Red
T_NESTED_TABLE_ADDRESS(
T_ADDRESS('10 Main Street', 'Green Town', 'CA', '22212'),
T_ADDRESS('20 State Street', 'Blue Town', 'FL', '22213'))
Pl/SQl CuIIcctiun Mcthuds
ln ths secton, you' see the lL/SQL methods you cun use wth coectons. 1ube l3-3
summurzes the coecton methods. 1hese methods cun be used ony n lL/SQL.
1he loowng sectons use u puckuge numed collection_method_examples, the exumpes
ustrute the use ol the methods shown n the prevous tube. 1he puckuge s creuted by the
collection_schema.sql scrpt, und you' see the ndvduu methods delned n ths puckuge
n the loowng sectons.
COUNT()
COUNT returns the number ol eements n u coecton. ecuuse u nested tube cun huve ndvduu
eements thut ure empty, COUNT returns the number ol non-empty eements n u nested tube. lor
exumpe, et's suy you huve u nested tube numed v_nested_table thut hus ts eements set us
shown n the loowng tube.
fIcmcnt lndcx fmpty/Nut fmpty
l Lmpty
2 Not empty
3 Lmpty
4 Not empty
Chupter l3: Coectons
449
Mcthud Dcscriptiun
COUNT
Returns the number ol eements n u coecton. ecuuse u nested tube
cun huve ndvduu eements thut ure empty, COUNT returns the number
ol non-empty eements n u nested tube.
DELETE
DELETE(n)
DELETE(n, m)
Removes eements lrom u coecton. 1here ure three lorms ol DELETE:
DELETE removes u eements.
DELETE(n) removes eement n.
DELETE(n, m) removes eements n through m.
ecuuse vurruys uwuys huve consecutve subscrpts, you cunnot deete
ndvduu eements lrom u vurruy (except lrom the end by usng TRIM).
EXISTS(n)
Returns true l eement n n u coecton exsts: EXISTS returns true lor
non-empty eements und luse lor empty eements ol nested tubes or
eements beyond the runge ol u coecton.
EXTEND
EXTEND(n)
EXTEND(n, m)
Adds eements to the end ol u coecton. 1here ure three lorms ol
EXTEND:
EXTEND udds one eement, whch s set to nu.
EXTEND(n) udds n eements, whch ure set to nu.
EXTEND(n, m) udds n eements, whch ure set to u copy ol the m
eement.
FIRST
Returns the ndex ol the lrst eement n u coecton. ll the coecton s
competey empty, FIRST returns nu. ecuuse u nested tube cun huve
ndvduu eements thut ure empty, FIRST returns the owest ndex ol u
non-empty eement n u nested tube.
LAST
Returns the ndex ol the ust eement n u coecton. ll the coecton s
competey empty, LAST returns nu. ecuuse u nested tube cun huve
ndvduu eements thut ure empty, LAST returns the hghest ndex ol u
non-empty eement n u nested tube.
LIMIT
lor nested tubes, whch huve no decured sze, LIMIT returns nu. lor
vurruys, LIMIT returns the muxmum number ol eements thut the vurruy
cun contun. You specly the mt n the type delnton. 1he mt s
chunged when usng TRIM und EXTEND, or when you use ALTER TYPE
to chunge the mt.
NEXT(n)
Returns the ndex ol the eement ulter n. ecuuse u nested tube cun huve
ndvduu eements thut ure empty, NEXT returns the ndex ol u non-
empty eement ulter n. ll there ure no eements ulter n, NEXT returns nu.
PRIOR(n)
Returns the ndex ol the eement belore n. ecuuse u nested tube cun huve
ndvduu eements thut ure empty, PRIOR returns the ndex ol u non-empty
eement belore n. ll there ure no eements belore n, PRIOR returns nu.
TRIM
TRIM(n)
Removes eements lrom the end ol u coecton. 1here ure two lorms ol
TRIM:
TRIM removes one eement lrom the end.
TRIM(n) removes n eements lrom the end.
TABlf 13-3 /S Cocc|on \c|hod

Cruce Dutubuse ll SQL
Cven ths conlguruton, v_nested_table.COUNT returns 2, the number ol non-empty
eements.
COUNT s used n the get_addresses() und display_addresses() methods ol the
collection_method_examples puckuge. 1he get_addresses() luncton returns the
specled customer's uddresses lrom customers_with_nested_table, whose id s pussed
to the luncton:
FUNCTION get_addresses(
p_id customers_with_nested_table.id%TYPE
) RETURN t_nested_table_address IS
-- declare object named v_addresses to store the
-- nested table of addresses
v_addresses t_nested_table_address;
BEGIN
-- retrieve the nested table of addresses into v_addresses
SELECT addresses
INTO v_addresses
FROM customers_with_nested_table
WHERE id = p_id;
-- display the number of addresses using v_addresses.COUNT
DBMS_OUTPUT.PUT_LINE(
'Number of addresses = '|| v_addresses.COUNT
);
-- return v_addresses
RETURN v_addresses;
END get_addresses;
1he loowng exumpe sets the server output on und cus get_addresses() lor customer rl:
SET SERVEROUTPUT ON
SELECT collection_method_examples.get_addresses(1) addresses
FROM dual;
ADDRESSES(STREET, CITY, STATE, ZIP)
--------------------------------------------------------
T_NESTED_TABLE_ADDRESS(
T_ADDRESS('2 State Street', 'Beantown', 'MA', '12345'),
T_ADDRESS('4 Hill Street', 'Lost Town', 'CA', '54321'))
Number of addresses = 2
1he loowng display_addresses() procedure uccepts u purumeter numed p_addresses,
whch contuns u nested tube ol uddresses, the procedure dspuys the number ol uddresses n p_
addresses usng COUNT, und then dspuys those uddresses usng u oop:
PROCEDURE display_addresses(
p_addresses t_nested_table_address
) IS
v_count INTEGER;
Chupter l3: Coectons
4S1
BEGIN
-- display the number of addresses in p_addresses
DBMS_OUTPUT.PUT_LINE(
'Current number of addresses = '|| p_addresses.COUNT
);
-- display the addresses in p_addresses using a loop
FOR v_count IN 1..p_addresses.COUNT LOOP
DBMS_OUTPUT.PUT_LINE('Address #' || v_count || ':');
DBMS_OUTPUT.PUT(p_addresses(v_count).street || ', ');
DBMS_OUTPUT.PUT(p_addresses(v_count).city || ', ');
DBMS_OUTPUT.PUT(p_addresses(v_count).state || ', ');
DBMS_OUTPUT.PUT_LINE(p_addresses(v_count).zip);
END LOOP;
END display_addresses;
You' see the use ol display_addresses() shorty.
DflfTf()
DELETE removes eements lrom u coecton. 1here ure three lorms ol DELETE:
DELETE removes u eements.
DELETE(n) removes eement n.
DELETE(n, m) removes eements n through m.
lor exumpe, et's suy you huve u nested tube numed v_nested_table thut hus seven
eements, then v_nested_table.DELETE(2, 5) removes eements 2 through 5.
1he loowng delete_address() procedure gets the uddresses lor customer rl und then
uses DELETE to remove the uddress whose ndex s specled by the p_address_num purumeter:
PROCEDURE delete_address(
p_address_num INTEGER
) IS
v_addresses t_nested_table_address;
BEGIN
v_addresses := get_addresses(1);
display_addresses(v_addresses);
DBMS_OUTPUT.PUT_LINE('Deleting address #' || p_address_num);
-- delete the address specified by p_address_num
v_addresses.DELETE(p_address_num);
display_addresses(v_addresses);
END delete_address;
1he loowng exumpe cus delete_address(2) to remove uddress r2 lrom customer rl:
CALL collection_method_examples.delete_address(2);
Number of addresses = 2
Current number of addresses = 2
4S2
Cruce Dutubuse ll SQL
Address #1:
2 State Street, Beantown, MA, 12345
Address #2:
4 Hill Street, Lost Town, CA, 54321
Deleting address #2
Current number of addresses = 1
Address #1:
2 State Street, Beantown, MA, 12345
fXlSTS()
EXISTS(n) returns true l eement n n u coecton exsts: EXISTS returns true lor non-empty
eements, und t returns luse lor empty eements ol nested tubes or eements beyond the runge ol
u coecton. lor exumpe, et's suy you huve u nested tube numed v_nested_table thut hus ts
eements set us shown n the loowng tube.
fIcmcnt lndcx fmpty/Nut fmpty
l Lmpty
2 Not empty
3 Lmpty
4 Not empty
Cven ths conlguruton, v_nested_table.EXISTS(2) returns true (becuuse eement r2
s not empty), und v_nested_table.EXISTS(3) returns luse (becuuse eement r3 s empty).
1he loowng exist_addresses() procedure gets the uddresses lor customer rl, uses
DELETE to remove uddress rl, und then uses EXISTS to check whether uddresses rl und r2
exst (rl does not exst becuuse t hus been deeted, r2 does exst):
PROCEDURE exist_addresses IS
v_addresses t_nested_table_address;
BEGIN
v_addresses := get_addresses(1);
DBMS_OUTPUT.PUT_LINE('Deleting address #1');
v_addresses.DELETE(1);
-- use EXISTS to check if the addresses exist
IF v_addresses.EXISTS(1) THEN
DBMS_OUTPUT.PUT_LINE('Address #1 does exist');
ELSE
DBMS_OUTPUT.PUT_LINE('Address #1 does not exist');
END IF;
IF v_addresses.EXISTS(2) THEN
DBMS_OUTPUT.PUT_LINE('Address #2 does exist');
END IF;
END exist_addresses;
1he loowng exumpe cus exist_addresses():
CALL collection_method_examples.exist_addresses();
Number of addresses = 2
Chupter l3: Coectons
4S3
Deleting address #1
Address #1 does not exist
Address #2 does exist
fXTfND()
EXTEND udds eements to the end ol u coecton. 1here ure three lorms ol EXTEND:
EXTEND udds one eement, whch s set to nu.
EXTEND(n) udds n eements, whch ure set to nu.
EXTEND(n, m) udds n eements, whch ure set to u copy ol the m eement.
lor exumpe, et's suy you huve u coecton numed v_nested_table thut hus seven
eements, then v_nested_table.EXTEND(2, 5) udds eement r5 twce to the end ol the
coecton.
1he loowng extend_addresses() procedure gets the uddresses lor customer rl nto
v_addresses, then uses EXTEND to copy uddress rl twce to the end ol v_addresses:
PROCEDURE extend_addresses IS
v_addresses t_nested_table_address;
BEGIN
v_addresses := get_addresses(1);
display_addresses(v_addresses);
DBMS_OUTPUT.PUT_LINE('Extending addresses');
-- copy address #1 twice to the end of v_addresses
v_addresses.EXTEND(2, 1);
display_addresses(v_addresses);
END extend_addresses;
1he loowng exumpe cus extend_addresses():
CALL collection_method_examples.extend_addresses();
Number of addresses = 2
Current number of addresses = 2
Address #1:
2 State Street, Beantown, MA, 12345
Address #2:
4 Hill Street, Lost Town, CA, 54321
Extending addresses
Current number of addresses = 4
Address #1:
2 State Street, Beantown, MA, 12345
Address #2:
4 Hill Street, Lost Town, CA, 54321
Address #3:
2 State Street, Beantown, MA, 12345
Address #4:
2 State Street, Beantown, MA, 12345
4S4
Cruce Dutubuse ll SQL
flRST()
You use FIRST to get the ndex ol the lrst eement n u coecton. ll the coecton s competey
empty, FIRST returns nu. ecuuse u nested tube cun huve ndvduu eements thut ure empty,
FIRST returns the owest ndex ol u non-empty eement n u nested tube. lor exumpe, et's suy
you huve u nested tube numed v_nested_table thut hus ts eements set us shown n the
loowng tube.
fIcmcnt lndcx fmpty/Nut fmpty
l Lmpty
2 Not empty
3 Lmpty
4 Not empty
Cven ths conlguruton, v_nested_table.FIRST returns 2, the owest ndex contunng u
non-empty eement.
1he loowng first_address() procedure gets the uddresses lor customer rl nto v_
addresses und then uses FIRST to dspuy the ndex ol the lrst uddress n v_addresses, the
procedure then deetes uddress rl usng DELETE und dspuys the new ndex returned by FIRST:
PROCEDURE first_address IS
v_addresses t_nested_table_address;
BEGIN
v_addresses := get_addresses(1);
-- display the FIRST address
DBMS_OUTPUT.PUT_LINE('First address = ' || v_addresses.FIRST);
DBMS_OUTPUT.PUT_LINE('Deleting address #1');
v_addresses.DELETE(1);
-- display the FIRST address again
DBMS_OUTPUT.PUT_LINE('First address = ' || v_addresses.FIRST);
END first_address;
1he loowng exumpe cus first_address():
CALL collection_method_examples.first_address();
Number of addresses = 2
First address = 1
Deleting address #1
First address = 2
lAST()
LAST returns the ndex ol the ust eement n u coecton. ll the coecton s competey empty, LAST
returns nu. ecuuse u nested tube cun huve ndvduu eements thut ure empty, LAST returns the
hghest ndex ol u non-empty eement n u nested tube. lor exumpe, et's suy you huve u nested
tube numed v_nested_table thut hus ts eements set us shown n the loowng tube.
Chupter l3: Coectons
4SS
fIcmcnt lndcx fmpty/Nut fmpty
l Not empty
2 Lmpty
3 Lmpty
4 Not empty
Cven ths conlguruton, v_nested_table.LAST returns 4, the hghest ndex contunng u
non-empty eement.
1he loowng last_address() procedure gets the uddresses lor customer rl nto v_
addresses und then uses LAST to dspuy the ndex ol the ust uddress n v_addresses, the
procedure then deetes uddress r2 usng DELETE und dspuys the new ndex returned by LAST:
PROCEDURE last_address IS
v_addresses t_nested_table_address;
BEGIN
v_addresses := get_addresses(1);
-- display the LAST address
DBMS_OUTPUT.PUT_LINE('Last address = ' || v_addresses.LAST);
DBMS_OUTPUT.PUT_LINE('Deleting address #2');
v_addresses.DELETE(2);
-- display the LAST address again
DBMS_OUTPUT.PUT_LINE('Last address = ' || v_addresses.LAST);
END last_address;
1he loowng exumpe cus last_address():
CALL collection_method_examples.last_address();
Number of addresses = 2
Last address = 2
Deleting address #2
Last address = 1
NfXT()
NEXT(n) returns the ndex ol the eement ulter n. ecuuse u nested tube cun huve ndvduu
eements thut ure empty, NEXT returns the ndex ol u non-empty eement ulter n. ll there ure no
eements ulter n, NEXT returns nu. lor exumpe, et's suy you huve u nested tube numed v_
nested_table thut hus ts eements set us shown n the loowng tube.
fIcmcnt lndcx fmpty/Nut fmpty
l Not empty
2 Lmpty
3 Lmpty
4 Not empty
4S6
Cruce Dutubuse ll SQL
Cven ths conlguruton, v_nested_table.NEXT(1) returns 4, the ndex contunng the
next non-empty eement, v_nested_table.NEXT(4) returns nu.
1he loowng next_address() procedure gets the uddresses lor customer rl nto v_
addresses und then uses NEXT(1) to get the ndex ol the uddress ulter uddress rl n v_
addresses, the procedure then uses NEXT(2) to uttempt to get the ndex ol the uddress ulter
uddress r2 (there sn't one, becuuse customer rl ony hus two uddresses, so nu s returned):
PROCEDURE next_address IS
v_addresses t_nested_table_address;
BEGIN
v_addresses := get_addresses(1);
-- use NEXT(1) to get the index of the address
-- after address #1
DBMS_OUTPUT.PUT_LINE(
'v_addresses.NEXT(1) = ' || v_addresses.NEXT(1)
);
-- use NEXT(2) to attempt to get the index of
-- the address after address #2 (there isn't one,
-- so null is returned)
DBMS_OUTPUT.PUT_LINE(
'v_addresses.NEXT(2) = ' || v_addresses.NEXT(2)
);
END next_address;
1he loowng exumpe cus next_address(), v_addresses.NEXT(2) s nu, und so no
output s shown ulter the = lor thut eement:
CALL collection_method_examples.next_address();
Number of addresses = 2
v_addresses.NEXT(1) = 2
v_addresses.NEXT(2) =
PRlOR()
PRIOR(n) returns the ndex ol the eement belore n. ecuuse u nested tube cun huve ndvduu
eements thut ure empty, PRIOR returns the ndex ol u non-empty eement belore n. ll there ure
no eements belore n, PRIOR returns nu. lor exumpe, et's suy you huve u nested tube numed
v_nested_table thut hus ts eements set us shown n the loowng tube.
fIcmcnt lndcx fmpty/Nut fmpty
l Not empty
2 Lmpty
3 Lmpty
4 Not empty
Cven ths conlguruton, v_nested_table.PRIOR(4) returns l, the ndex contunng the
pror non-empty eement, v_nested_table.PRIOR(1) returns nu.
Chupter l3: Coectons
4S7
1he loowng prior_address() procedure gets the uddresses lor customer rl nto v_
addresses und then uses PRIOR(2) to get the ndex ol the uddress belore uddress r2 n v_
addresses, the procedure then uses PRIOR(1) to uttempt to get the ndex ol the uddress belore
uddress rl (there sn't one, so nu s returned):
PROCEDURE prior_address IS
v_addresses t_nested_table_address;
BEGIN
v_addresses := get_addresses(1);
-- use PRIOR(2) to get the index of the address
-- before address #2
DBMS_OUTPUT.PUT_LINE(
'v_addresses.PRIOR(2) = ' || v_addresses.PRIOR(2)
);
-- use PRIOR(1) to attempt to get the index of
-- the address before address #1 (there isn't one,
-- so null is returned)
DBMS_OUTPUT.PUT_LINE(
'v_addresses.PRIOR(1) = ' || v_addresses.PRIOR(1)
);
END prior_address;
1he loowng exumpe cus prior_address(), v_addresses.PRIOR(1) s nu, und so
no output s shown ulter the = lor thut eement:
CALL collection_method_examples.prior_address();
Number of addresses = 2
v_addresses.PRIOR(2) = 1
v_addresses.PRIOR(1) =
TRlM()
TRIM removes eements lrom the end ol u coecton. 1here ure two lorms ol TRIM:
TRIM removes one eement lrom the end.
TRIM(n) removes n eements lrom the end.
lor exumpe, et's suy you huve u nested tube numed v_nested_table, then v_nested_
table.TRIM(2) removes two eements lrom the end.
1he loowng trim_addresses() procedure gets the uddresses ol customer rl, copes
uddress rl to the end ol v_addresses three tmes usng EXTEND(3, 1), und then removes
two uddresses lrom the end ol v_addresses usng TRIM(2):
PROCEDURE trim_addresses IS
v_addresses t_nested_table_address;
BEGIN
v_addresses := get_addresses(1);
display_addresses(v_addresses);
DBMS_OUTPUT.PUT_LINE('Extending addresses');
4S8
Cruce Dutubuse llg SQL
v_addresses.EXTEND(3, 1);
display_addresses(v_addresses);
DBMS_OUTPUT.PUT_LINE('Trimming 2 addresses from end');
-- remove 2 addresses from the end of v_addresses
-- using TRIM(2)
v_addresses.TRIM(2);
display_addresses(v_addresses);
END trim_addresses;
1he loowng exumpe cus trim_addresses():
CALL collection_method_examples.trim_addresses();
Number of addresses = 2
Current number of addresses = 2
Address #1:
2 State Street, Beantown, MA, 12345
Address #2:
4 Hill Street, Lost Town, CA, 54321
Extending addresses
Current number of addresses = 5
Address #1:
2 State Street, Beantown, MA, 12345
Address #2:
4 Hill Street, Lost Town, CA, 54321
Address #3:
2 State Street, Beantown, MA, 12345
Address #4:
2 State Street, Beantown, MA, 12345
Address #5:
2 State Street, Beantown, MA, 12345
Trimming 2 addresses from end
Current number of addresses = 3
Address #1:
2 State Street, Beantown, MA, 12345
Address #2:
4 Hill Street, Lost Town, CA, 54321
Address #3:
2 State Street, Beantown, MA, 12345
MuItiIcvcI CuIIcctiuns
\th the reeuse ol Cruce Dutubuse 9, you cun creute u coecton n the dutubuse whose
eements ure uso u coecton. 1hese coectons ol coectons ure known us mu|cvc
cocc|on. 1he loowng st shows the vud muteve coectons:
A nested tube ol nested tubes
A nested tube ol vurruys
A vurruy ol vurruys
A vurruy ol nested tubes
Chupter l3: Coectons

l've provded un SQL*lus scrpt numed collection_schema2.sql n the SQL drectory.


1hs scrpt creutes u user numed collection_user2, wth u pussword ol collection_
password, uong wth the types und the tube shown n ths secton. You cun run ths scrpt l
you ure usng Cruce Dutubuse 9 or hgher. Alter the scrpt competes, you w be ogged n us
collection_user2.
Let's suy you wunted to store u set ol phone numbers lor euch uddress ol u customer. 1he
loowng exumpe creutes u vurruy type ol three VARCHAR2 strngs numed t_varray_phone
to represent phone numbers:
CREATE TYPE t_varray_phone AS VARRAY(3) OF VARCHAR2(14);
/
Next, the loowng exumpe creutes un obect type numed t_address thut contuns un
uttrbute numed phone_numbers, ths uttrbute s ol type t_varray_phone:
CREATE TYPE t_address AS OBJECT (
street VARCHAR2(15),
city VARCHAR2(15),
state CHAR(2),
zip VARCHAR2(5),
phone_numbers t_varray_phone
);
/
1he next exumpe creutes u nested tube type ol t_address obects:
CREATE TYPE t_nested_table_address AS TABLE OF t_address;
/
1he loowng exumpe creutes u tube numed customers_with_nested_table, whch
contuns u coumn numed addresses ol type t_nested_table_address:
CREATE TABLE customers_with_nested_table (
id INTEGER PRIMARY KEY,
first_name VARCHAR2(10),
last_name VARCHAR2(10),
addresses t_nested_table_address
)
NESTED TABLE
addresses
STORE AS
nested_addresses;
So, customers_with_nested_table contuns u nested tube whose eements contun un
uddress wth u vurruy ol phone numbers.
1he loowng INSERT stutement udds u row to customers_with_nested_table, notce
the structure und content ol the INSERT stutement, whch contuns eements lor the nested tube
ol uddresses, euch ol whch hus un embedded vurruy ol phone numbers:
INSERT INTO customers_with_nested_table VALUES (
1, 'Steve', 'Brown',
t_nested_table_address(
t_address('2 State Street', 'Beantown', 'MA', '12345',

Cruce Dutubuse ll SQL
t_varray_phone(
'(800)-555-1211',
'(800)-555-1212',
'(800)-555-1213'
)
),
t_address('4 Hill Street', 'Lost Town', 'CA', '54321',
t_varray_phone(
'(800)-555-1211',
'(800)-555-1212'
)
)
)
);
You cun see thut the lrst uddress hus three phone numbers, whe the second uddress hus two.
1he loowng query retreves the row lrom customers_with_nested_table:
SELECT *
FROM customers_with_nested_table;
ID FIRST_NAME LAST_NAME
---------- ---------- ----------
ADDRESSES(STREET, CITY, STATE, ZIP, PHONE_NUMBERS)
------------------------------------------------------------------------
1 Steve Brown
T_NESTED_TABLE_ADDRESS(
T_ADDRESS('2 State Street', 'Beantown', 'MA', '12345',
T_VARRAY_PHONE('(800)-555-1211', '(800)-555-1212', '(800)-555-1213')),
T_ADDRESS('4 Hill Street', 'Lost Town', 'CA', '54321',
T_VARRAY_PHONE('(800)-555-1211', '(800)-555-1212')))
You cun use TABLE() to treut the dutu stored n the coectons us u seres ol rows, us shown
n the loowng query:
SELECT cn.first_name, cn.last_name, a.street, a.city, a.state, p.*
FROM customers_with_nested_table cn,
TABLE(cn.addresses) a, TABLE(a.phone_numbers) p;
FIRST_NAME LAST_NAME STREET CITY ST COLUMN_VALUE
---------- ---------- --------------- ------------ -- --------------
Steve Brown 2 State Street Beantown MA (800)-555-1211
Steve Brown 2 State Street Beantown MA (800)-555-1212
Steve Brown 2 State Street Beantown MA (800)-555-1213
Steve Brown 4 Hill Street Lost Town CA (800)-555-1211
Steve Brown 4 Hill Street Lost Town CA (800)-555-1212
1he loowng UPDATE stutement shows how to updute the phone numbers lor the 2 State
Street uddress, notce thut TABLE() s used to get the uddresses us u seres ol rows und thut u
vurruy contunng the new phone numbers s supped n the SET cuuse:
Chupter l3: Coectons
461
UPDATE TABLE(
-- get the addresses for customer #1
SELECT cn.addresses
FROM customers_with_nested_table cn
WHERE cn.id = 1
) addrs
SET addrs.phone_numbers =
t_varray_phone(
'(800)-555-1214',
'(800)-555-1215'
)
WHERE addrs.street = '2 State Street';
1 row updated.
1he loowng query verles the chunge:
SELECT cn.first_name, cn.last_name, a.street, a.city, a.state, p.*
FROM customers_with_nested_table cn,
TABLE(cn.addresses) a, TABLE(a.phone_numbers) p;
FIRST_NAME LAST_NAME STREET CITY ST COLUMN_VALUE
---------- ---------- --------------- ------------ -- --------------
Steve Brown 2 State Street Beantown MA (800)-555-1214
Steve Brown 2 State Street Beantown MA (800)-555-1215
Steve Brown 4 Hill Street Lost Town CA (800)-555-1211
Steve Brown 4 Hill Street Lost Town CA (800)-555-1212
Support lor muteve coecton types s u very powerlu extenson to the Cruce dutubuse
soltwure, und you mght wunt to consder usng them n uny dutubuse desgns you contrbute to.
OracIc Databasc 10 fnhanccmcnts tu CuIIcctiuns
ln ths secton, you' eurn ubout the loowng enhuncements mude to coectons n Cruce
Dutubuse l0:
Support lor ussocutve urruys
Abty to chunge the sze or precson ol un eement type
Abty to ncreuse the number ol eements n u vurruy
Abty to use vurruy coumns n temporury tubes
Abty to use u dllerent tubespuce lor u nested tube's storuge tube
ANSl support lor nested tubes
1he vurous stutements thut creute the tems shown n ths secton ure contuned n the
collection_schema3.sql scrpt. 1hs scrpt creutes u user numed collection_user3
462
Cruce Dutubuse ll SQL
wth u pussword ol collection_password und creutes the coecton types, tubes, und lL/
SQL code. You cun run ths scrpt l you ure usng Cruce Dutubuse l0 or hgher. Alter the scrpt
competes, you w be ogged n us collection_user3.
Assuciativc Arrays
An ussocutve urruy s u set ol key und vuue purs. You cun get the vuue lrom the urruy usng the
key (whch muy be u strng) or un nteger thut specles the poston ol the vuue n the urruy. 1he
loowng exumpe procedure numed customers_associative_array() ustrutes the use
ol ussocutve urruys:
CREATE PROCEDURE customers_associative_array AS
-- define an associative array type named t_assoc_array;
-- the value stored in each array element is a NUMBER,
-- and the index key to access each element is a VARCHAR2
TYPE t_assoc_array IS TABLE OF NUMBER INDEX BY VARCHAR2(15);
-- declare an object named v_customer_array of type t_assoc_array;
-- v_customer_array will be used to store the ages of customers
v_customer_array t_assoc_array;
BEGIN
-- assign the values to v_customer_array; the VARCHAR2 key is the
-- customer name and the NUMBER value is the age of the customer
v_customer_array('Jason') := 32;
v_customer_array('Steve') := 28;
v_customer_array('Fred') := 43;
v_customer_array('Cynthia') := 27;
-- display the values stored in v_customer_array
DBMS_OUTPUT.PUT_LINE(
'v_customer_array[''Jason''] = ' || v_customer_array('Jason')
);
DBMS_OUTPUT.PUT_LINE(
'v_customer_array[''Steve''] = ' || v_customer_array('Steve')
);
DBMS_OUTPUT.PUT_LINE(
'v_customer_array[''Fred''] = ' || v_customer_array('Fred')
);
DBMS_OUTPUT.PUT_LINE(
'v_customer_array[''Cynthia''] = ' || v_customer_array('Cynthia')
);
END customers_associative_array;
/
1he loowng exumpe sets the server output on und cus customers_associative_
array():
SET SERVEROUTPUT ON
CALL customers_associative_array();
v_customer_array['Jason'] = 32
v_customer_array['Steve'] = 28
v_customer_array['Fred'] = 43
v_customer_array['Cynthia'] = 27
Chupter l3: Coectons
463
Changing thc Sizc uf an fIcmcnt Typc
You cun chunge the sze ol un eement type n u coecton when the eement type s one ol the
churucter, numerc, or ruw types (ruw s used to store bnury dutu you' eurn ubout ths n the
next chupter). Lurer n ths chupter, you suw the loowng stutement thut creutes u vurruy type
numed t_varray_address:
CREATE TYPE t_varray_address AS VARRAY(2) OF VARCHAR2(50);
/
1he loowng exumpe chunges the sze ol the VARCHAR2 eements n t_varray_address
to 60:
ALTER TYPE t_varray_address
MODIFY ELEMENT TYPE VARCHAR2(60) CASCADE;
Type altered.
1he CASCADE opton propugutes the chunge to uny dependent obects n the dutubuse,
whch, n the exumpe, s the customers_with_varray tube thut contuns u coumn numed
addresses ol type t_varray_address. You cun uso use the INVALIDATE opton to
nvudute uny dependent obects und mmedutey recompe the lL/SQL code lor the type.
lncrcasing thc Numbcr uf fIcmcnts in a Varray
You cun ncreuse the number ol eements n u vurruy. 1he loowng exumpe ncreuses the
number ol eements n t_varray_address to 5:
ALTER TYPE t_varray_address
MODIFY LIMIT 5 CASCADE;
Type altered.
Using Varrays in Tcmpurary TabIcs
You cun use vurruys n temporury tubes, whch ure tubes whose rows ure temporury und ure
speclc to u user sesson (temporury tubes were covered n the secton Creutng u 1ube n
Chupter l0). 1he loowng exumpe creutes u temporury tube numed cust_with_varray_
temp_table thut contuns u vurruy numed addresses ol type t_varray_address:
CREATE GLOBAL TEMPORARY TABLE cust_with_varray_temp_table (
id INTEGER PRIMARY KEY,
first_name VARCHAR2(10),
last_name VARCHAR2(10),
addresses t_varray_address
);
Using a Diffcrcnt TabIcspacc fur a Ncstcd TabIc's
Sturagc TabIc
y deluut, u nested tube's storuge tube s creuted n the sume tubespuce us the purent tube
(u tubespuce s un ureu used by the dutubuse to store obects such us tubessee the secton
Creutng u 1ube n Chupter l0 lor detus).
464
Cruce Dutubuse ll SQL
ln Cruce Dutubuse l0 und hgher, you cun specly u dllerent tubespuce lor u nested tube's
storuge tube. 1he loowng exumpe creutes u tube numed cust_with_nested_table thut
contuns u nested tube numed addresses ol type t_nested_table_address, notce thut the
tubespuce lor the nested_addresses2 storuge tube s the users tubespuce:
CREATE TABLE cust_with_nested_table (
id INTEGER PRIMARY KEY,
first_name VARCHAR2(10),
last_name VARCHAR2(10),
addresses t_nested_table_address
)
NESTED TABLE
addresses
STORE AS
nested_addresses2 TABLESPACE users;
You must huve u tubespuce numed users n order lor ths exumpe to work, und lor ths
reuson l've commented out the exumpe n the collection_schema3.sql scrpt. You cun
see u the tubespuces you huve uccess to by perlormng the loowng query:
SELECT tablespace_name
FROM user_tablespaces;
TABLESPACE_NAME
---------------
SYSTEM
SYSAUX
UNDOTBS1
TEMP
USERS
EXAMPLE
ll you wunt to run the prevous CREATE TABLE stutement, you cun edt the exumpe n the
collection_schema3.sql scrpt to relerence one ol your tubespuces und then copy the
stutement nto SQL*lus und run t.
ANSl Suppurt fur Ncstcd TabIcs
1he Amercun Nutonu Stundurds lnsttute (ANSl) speclcuton ncudes u number ol operutors
thut muy be used wth nested tubes. You' eurn ubout these operutors n the loowng sectons.
fquaI and Nut-fquaI Opcraturs
1he equu (=) und not-equu (<>) operutors compure two nested tubes, whch ure consdered
equu when they sutsly u the loowng condtons:
1he tubes ure the sume type.
1he tubes ure the sume curdnuty, thut s, they contun the sume number ol eements.
A the eements ol the tube huve the sume vuue.
1he loowng equal_example() procedure ustrutes the use ol the equu und not-equu
operutors:
Chupter l3: Coectons
46S
CREATE PROCEDURE equal_example AS
-- declare a type named t_nested_table
TYPE t_nested_table IS TABLE OF VARCHAR2(10);
-- create t_nested_table objects named v_customer_nested_table1,
-- v_customer_nested_table2, and v_customer_nested_table3;
-- these objects are used to store the names of customers
v_customer_nested_table1 t_nested_table :=
t_nested_table('Fred', 'George', 'Susan');
v_customer_nested_table2 t_nested_table :=
t_nested_table('Fred', 'George', 'Susan');
v_customer_nested_table3 t_nested_table :=
t_nested_table('John', 'George', 'Susan');
v_result BOOLEAN;
BEGIN
-- use = operator to compare v_customer_nested_table1 with
-- v_customer_nested_table2 (they contain the same names, so
-- v_result is set to true)
v_result := v_customer_nested_table1 = v_customer_nested_table2;
IF v_result THEN
DBMS_OUTPUT.PUT_LINE(
'v_customer_nested_table1 equal to v_customer_nested_table2'
);
END IF;
-- use <> operator to compare v_customer_nested_table1 with
-- v_customer_nested_table3 (they are not equal because the first
-- names, 'Fred' and 'John', are different and v_result is set
-- to true)
v_result := v_customer_nested_table1 <> v_customer_nested_table3;
IF v_result THEN
DBMS_OUTPUT.PUT_LINE(
'v_customer_nested_table1 not equal to v_customer_nested_table3'
);
END IF;
END equal_example;
/
1he loowng exumpe cus equal_example():
CALL equal_example();
v_customer_nested_table1 equal to v_customer_nested_table2
v_customer_nested_table1 not equal to v_customer_nested_table3
lN and NOT lN Opcraturs
1he IN operutor checks l the eements ol one nested tube uppeur n unother nested tube.
Smury, NOT IN checks l the eements ol one nested tube do not uppeur n unother nested
tube. 1he loowng in_example() procedure ustrutes the use ol IN und NOT IN:
CREATE PROCEDURE in_example AS
TYPE t_nested_table IS TABLE OF VARCHAR2(10);
466
Cruce Dutubuse ll SQL
v_customer_nested_table1 t_nested_table :=
t_nested_table('Fred', 'George', 'Susan');
v_customer_nested_table2 t_nested_table :=
t_nested_table('John', 'George', 'Susan');
v_customer_nested_table3 t_nested_table :=
t_nested_table('Fred', 'George', 'Susan');
v_result BOOLEAN;
BEGIN
-- use IN operator to check if elements of v_customer_nested_table3
-- are in v_customer_nested_table1 (they are, so v_result is
-- set to true)
v_result := v_customer_nested_table3 IN
(v_customer_nested_table1);
IF v_result THEN
DBMS_OUTPUT.PUT_LINE(
'v_customer_nested_table3 in v_customer_nested_table1'
);
END IF;
-- use NOT IN operator to check if the elements of
-- v_customer_nested_table3 are not in v_customer_nested_table2
-- (they are not, so v_result is set to true)
v_result := v_customer_nested_table3 NOT IN
(v_customer_nested_table2);
IF v_result THEN
DBMS_OUTPUT.PUT_LINE(
'v_customer_nested_table3 not in v_customer_nested_table2'
);
END IF;
END in_example;
/
1he loowng exumpe cus in_example():
CALL in_example();
v_customer_nested_table3 in v_customer_nested_table1
v_customer_nested_table3 not in v_customer_nested_table2
SUBMUlTlSfT Opcratur
1he SUBMULTISET operutor checks whether the eements ol one nested tube ure u subset ol
unother nested tube. 1he loowng submultiset_example() procedure ustrutes the use
ol SUBMULTISET:
CREATE PROCEDURE submultiset_example AS
TYPE t_nested_table IS TABLE OF VARCHAR2(10);
v_customer_nested_table1 t_nested_table :=
t_nested_table('Fred', 'George', 'Susan');
v_customer_nested_table2 t_nested_table :=
t_nested_table('George', 'Fred', 'Susan', 'John', 'Steve');
v_result BOOLEAN;
BEGIN
Chupter l3: Coectons
467
-- use SUBMULTISET operator to check if elements of
-- v_customer_nested_table1 are a subset of v_customer_nested_table2
-- (they are, so v_result is set to true)
v_result :=
v_customer_nested_table1 SUBMULTISET OF v_customer_nested_table2;
IF v_result THEN
DBMS_OUTPUT.PUT_LINE(
'v_customer_nested_table1 subset of v_customer_nested_table2'
);
END IF;
END submultiset_example;
/
1he loowng exumpe cus submultiset_example():
CALL submultiset_example();
customer_nested_table1 subset of customer_nested_table2
MUlTlSfT Opcratur
1he MULTISET operutor returns u nested tube whose eements ure set to certun combnutons ol
eements lrom two supped nested tubes. 1here ure three MULTISET operutors:
MULTISET UNION returns u nested tube whose eements ure set to the sum ol the
eements lrom two supped nested tubes.
MULTISET INTERSECT returns u nested tube whose eements ure set to the eements
thut ure common to two supped nested tubes.
MULTISET EXCEPT returns u nested tube whose eements ure n the lrst supped
nested tube but not n the second.
You muy uso use one ol the loowng optons wth MULTISET:
ALL ndcutes thut u the uppcube eements ure n the returned nested tube. ALL s the
deluut. lor exumpe, MULTISET UNION ALL returns u nested tube whose eements ure
set to the sum ol eements lrom two supped nested tubes, und u eements, ncudng
dupcutes, ure n the returned nested tube.
DISTINCT ndcutes thut ony the non-dupcute (thut s, dstnct) eements ure n the
returned nested tube. lor exumpe, MULTISET UNION DISTINCT returns u nested
tube whose eements ure set to the sum ol eements lrom two supped nested tubes,
but dupcutes ure removed lrom the returned nested tube.
1he loowng multiset_example() procedure ustrutes the use ol MULTISET:
CREATE PROCEDURE multiset_example AS
TYPE t_nested_table IS TABLE OF VARCHAR2(10);
v_customer_nested_table1 t_nested_table :=
t_nested_table('Fred', 'George', 'Susan');
v_customer_nested_table2 t_nested_table :=
t_nested_table('George', 'Steve', 'Rob');
v_customer_nested_table3 t_nested_table;

Cruce Dutubuse ll SQL
v_count INTEGER;
BEGIN
-- use MULTISET UNION (returns a nested table whose elements
-- are set to the sum of the two supplied nested tables)
v_customer_nested_table3 :=
v_customer_nested_table1 MULTISET UNION
v_customer_nested_table2;
DBMS_OUTPUT.PUT('UNION: ');
FOR v_count IN 1..v_customer_nested_table3.COUNT LOOP
DBMS_OUTPUT.PUT(v_customer_nested_table3(v_count) || ' ');
END LOOP;
DBMS_OUTPUT.PUT_LINE(' ');
-- use MULTISET UNION DISTINCT (DISTINCT indicates that only
-- the non-duplicate elements of the two supplied nested tables
-- are set in the returned nested table)
v_customer_nested_table3 :=
v_customer_nested_table1 MULTISET UNION DISTINCT
v_customer_nested_table2;
DBMS_OUTPUT.PUT('UNION DISTINCT: ');
FOR v_count IN 1..v_customer_nested_table3.COUNT LOOP
DBMS_OUTPUT.PUT(v_customer_nested_table3(v_count) || ' ');
END LOOP;
DBMS_OUTPUT.PUT_LINE(' ');
-- use MULTISET INTERSECT (returns a nested table whose elements
-- are set to the elements that are common to the two supplied
-- nested tables)
v_customer_nested_table3 :=
v_customer_nested_table1 MULTISET INTERSECT
v_customer_nested_table2;
DBMS_OUTPUT.PUT('INTERSECT: ');
FOR v_count IN 1..v_customer_nested_table3.COUNT LOOP
DBMS_OUTPUT.PUT(v_customer_nested_table3(v_count) || ' ');
END LOOP;
DBMS_OUTPUT.PUT_LINE(' ');
-- use MULTISET EXCEPT (returns a nested table whose
-- elements are in the first nested table but not in
-- the second)
v_customer_nested_table3 :=
v_customer_nested_table1 MULTISET EXCEPT
v_customer_nested_table2;
DBMS_OUTPUT.PUT_LINE('EXCEPT: ');
FOR v_count IN 1..v_customer_nested_table3.COUNT LOOP
DBMS_OUTPUT.PUT(v_customer_nested_table3(v_count) || ' ');
END LOOP;
END multiset_example;
/
Chupter l3: Coectons
469
1he loowng exumpe cus multiset_example():
CALL multiset_example();
UNION: Fred George Susan George Steve Rob
UNION DISTINCT: Fred George Susan Steve Rob
INTERSECT: George
EXCEPT:
CARDlNAllTY() functiun
1he CARDINALITY() luncton returns the number ol eements n u coecton. 1he loowng
cardinality_example() procedure ustrutes the use ol CARDINALITY():
CREATE PROCEDURE cardinality_example AS
TYPE t_nested_table IS TABLE OF VARCHAR2(10);
v_customer_nested_table1 t_nested_table :=
t_nested_table('Fred', 'George', 'Susan');
v_cardinality INTEGER;
BEGIN
-- call CARDINALITY() to get the number of elements in
-- v_customer_nested_table1
v_cardinality := CARDINALITY(v_customer_nested_table1);
DBMS_OUTPUT.PUT_LINE('v_cardinality = ' || v_cardinality);
END cardinality_example;
/
1he loowng exumpe cus cardinality_example():
CALL cardinality_example();
v_cardinality = 3
MfMBfR Of Opcratur
1he MEMBER OF operutor checks whether un eement s n u nested tube. 1he loowng
member_of_example() procedure ustrutes the use ol MEMBER OF:
CREATE PROCEDURE member_of_example AS
TYPE t_nested_table IS TABLE OF VARCHAR2(10);
v_customer_nested_table1 t_nested_table :=
t_nested_table('Fred', 'George', 'Susan');
v_result BOOLEAN;
BEGIN
-- use MEMBER OF to check if 'George' is in
-- v_customer_nested_table1 (he is, so v_result is set
-- to true)
v_result := 'George' MEMBER OF v_customer_nested_table1;
IF v_result THEN
DBMS_OUTPUT.PUT_LINE('''George'' is a member');
END IF;
END member_of_example;
/
470
Cruce Dutubuse ll SQL
1he loowng exumpe cus member_of_example():
CALL member_of_example();
'George' is a member
SfT() functiun
1he SET() luncton lrst converts u nested tube nto u set, then removes dupcute eements lrom
the set, und lnuy returns the set us u nested tube. 1he loowng set_example() procedure
ustrutes the use ol SET():
CREATE PROCEDURE set_example AS
TYPE t_nested_table IS TABLE OF VARCHAR2(10);
v_customer_nested_table1 t_nested_table :=
t_nested_table('Fred', 'George', 'Susan', 'George');
v_customer_nested_table2 t_nested_table;
v_count INTEGER;
BEGIN
-- call SET() to convert a nested table into a set,
-- remove duplicate elements from the set, and get the set
-- as a nested table
v_customer_nested_table2 := SET(v_customer_nested_table1);
DBMS_OUTPUT.PUT('v_customer_nested_table2: ');
FOR v_count IN 1..v_customer_nested_table2.COUNT LOOP
DBMS_OUTPUT.PUT(v_customer_nested_table2(v_count) || ' ');
END LOOP;
DBMS_OUTPUT.PUT_LINE(' ');
END set_example;
/
1he loowng exumpe cus set_example():
CALL set_example();
v_customer_nested_table2: Fred George Susan
lS A SfT Opcratur
1he IS A SET operutor checks l the eements n u nested tube ure dstnct. 1he loowng is_
a_set_example() procedure ustrutes the use ol IS A SET:
CREATE PROCEDURE is_a_set_example AS
TYPE t_nested_table IS TABLE OF VARCHAR2(10);
v_customer_nested_table1 t_nested_table :=
t_nested_table('Fred', 'George', 'Susan', 'George');
v_result BOOLEAN;
BEGIN
-- use IS A SET operator to check if the elements in
-- v_customer_nested_table1 are distinct (they are not, so
-- v_result is set to false)
v_result := v_customer_nested_table1 IS A SET;
IF v_result THEN
DBMS_OUTPUT.PUT_LINE('Elements are all unique');
ELSE
DBMS_OUTPUT.PUT_LINE('Elements contain duplicates');
END IF;
Chupter l3: Coectons
471
END is_a_set_example;
/
1he loowng exumpe cus is_a_set_example():
CALL is_a_set_example();
Elements contain duplicates
lS fMPTY Opcratur
1he IS EMPTY operutor checks l u nested tube doesn't contun eements. 1he loowng is_
empty_example() procedure ustrutes the use ol IS EMPTY:
CREATE PROCEDURE is_empty_example AS
TYPE t_nested_table IS TABLE OF VARCHAR2(10);
v_customer_nested_table1 t_nested_table :=
t_nested_table('Fred', 'George', 'Susan');
v_result BOOLEAN;
BEGIN
-- use IS EMPTY operator to check if
-- v_customer_nested_table1 is empty (it is not, so
-- v_result is set to false)
v_result := v_customer_nested_table1 IS EMPTY;
IF v_result THEN
DBMS_OUTPUT.PUT_LINE('Nested table is empty');
ELSE
DBMS_OUTPUT.PUT_LINE('Nested table contains elements');
END IF;
END is_empty_example;
/
1he loowng exumpe cus is_empty_example():
CALL is_empty_example();
Nested table contains elements
COllfCT() functiun
1he COLLECT() luncton returns u nested tube lrom u set ol eements. 1he loowng query
ustrutes the use ol COLLECT():
SELECT COLLECT(first_name)
FROM customers_with_varray;
COLLECT(FIRST_NAME)
----------------------------------------------
SYSTPfrFhAg+WRJGwW7ma9zy1KA==('Steve', 'John')
You cun use CAST() to convert the eements returned by COLLECT() to u speclc type, us
shown n the loowng query:
SELECT CAST(COLLECT(first_name) AS t_table)
FROM customers_with_varray;
CAST(COLLECT(FIRST_NAME)AST_TABLE)
----------------------------------
T_TABLE('Steve', 'John')
472
Cruce Dutubuse ll SQL
lor your relerence, the t_table type used n the prevous exumpe s creuted by the
loowng stutement n the collection_schema3.sql scrpt:
CREATE TYPE t_table AS TABLE OF VARCHAR2(10);
/
POWfRMUlTlSfT() functiun
1he POWERMULTISET() luncton returns u combnutons ol eements n u gven nested tube, us
shown n the loowng query:
SELECT *
FROM TABLE(
POWERMULTISET(t_table('This', 'is', 'a', 'test'))
);
COLUMN_VALUE
----------------------------------
T_TABLE('This')
T_TABLE('is')
T_TABLE('This', 'is')
T_TABLE('a')
T_TABLE('This', 'a')
T_TABLE('is', 'a')
T_TABLE('This', 'is', 'a')
T_TABLE('test')
T_TABLE('This', 'test')
T_TABLE('is', 'test')
T_TABLE('This', 'is', 'test')
T_TABLE('a', 'test')
T_TABLE('This', 'a', 'test')
T_TABLE('is', 'a', 'test')
T_TABLE('This', 'is', 'a', 'test')
POWfRMUlTlSfT_BY_CARDlNAllTY() functiun
1he POWERMULTISET_BY_CARDINALITY() luncton returns the combnutons ol eements n u
gven nested tube thut huve u specled number ol eements (or curdnuty). 1he loowng query
ustrutes the use ol POWERMULTISET_BY_CARDINALITY(), speclyng u curdnuty ol 3:
SELECT *
FROM TABLE(
POWERMULTISET_BY_CARDINALITY(
t_table('This', 'is', 'a', 'test'), 3
)
);
COLUMN_VALUE
-----------------------------
T_TABLE('This', 'is', 'a')
T_TABLE('This', 'is', 'test')
T_TABLE('This', 'a', 'test')
T_TABLE('is', 'a', 'test')
Chupter l3: Coectons
473
Summary
ln ths chupter, you huve eurned the loowng:
Coectons uow you to store sets ol eements.
1here ure three types ol coectons: vurruys, nested tubes, und ussocutve urruys.
A vurruy s smur to un urruy n }uvu, you cun use u vurruy to store un ordered set ol
eements wth euch eement huvng un ndex ussocuted wth t. 1he eements n u vurruy
ure ol the sume type, und u vurruy hus one dmenson. A vurruy hus u muxmum sze thut
you set when creutng t, but you cun chunge the sze uter.
A nested tube s u tube thut s embedded wthn unother tube, und you cun nsert,
updute, und deete ndvduu eements n u nested tube. ecuuse you cun modly
ndvduu eements n u nested tube, they ure more lexbe thun u vurruyu vurruy
cun be modled ony us u whoe. A nested tube doesn't huve u muxmum sze, und
you cun store un urbtrury number ol eements n u nested tube.
An ussocutve urruy s u set ol key und vuue purs. You cun get the vuue lrom the urruy
usng the key (whch muy be u strng) or un nteger thut specles the poston ol the vuue
n the urruy. An ussocutve urruy s smur to u hush tube n progrummng unguuges
such us }uvu.
A coecton muy tsel contun embedded coectons. Such u coecton s known us u
muteve coecton.
ln the next chupter, you' eurn ubout urge obects.
This page intentionally left blank
\IAI1II
14
Lurge Cbects
475
476
Cruce Dutubuse llg SQL
n ths chupter, you w do the loowng:
Leurn ubout urge obects (LCs)
See les whose content w be used to popuute exumpe LCs
Lxumne the dllerences between the dllerent types ol LCs
Creute tubes contunng LCs
Lse LCs n SQL und lL/SQL
Lxumne the LONG und LONG RAW types
See the Cruce Dutubuse l0g und llg enhuncements to LCs
lntruducing largc Objccts (lOBs)
1oduy's webstes demund more thun ust the storuge und retrevu ol text und numbers: they uso
requre mutmedu. Consequenty, dutubuses ure now beng cued upon to store tems ke musc
und vdeo. lror to the reeuse ol Cruce Dutubuse 8, you hud to store urge bocks ol churucter
dutu usng the LONG dutubuse type, und urge bocks ol bnury dutu hud to be stored usng ether
the LONG RAW type or the shorter RAW type.
\th the reeuse Cruce Dutubuse 8, u new cuss ol dutubuse types known us argc ob]cc|s,
or LCs lor short, wus ntroduced. LCs muy be used to store bnury dutu, churucter dutu, und
relerences to les. 1he bnury dutu cun contun muges, musc, vdeo, documents, executubes,
und so on. LCs cun store up to l28 terubytes ol dutu, dependng on the dutubuse conlguruton.
Thc fxampIc fiIcs
You' see the use ol the loowng two les n ths chupter:
textContent.txt A text le
binaryContent.doc A Mcrosolt \ord le
NOTf
Thcc |c arc con|ancd n |hc sample_files drcc|or,, vhch
crca|cd vhcn ,ou cx|rac| |hc Zp |c |or |h boo|. | ,ou van| |o
|oov aong v|h |hc cxampc, ,ou houd cop, |hc sample_files
drcc|or, |o |hc C par||on on ,our da|abac crvcr. | ,ou'rc ung
nux or Lnx, ,ou can cop, |hc drcc|or, |o onc o| ,our par||on.

Chupter l4: Lurge Cbects


477
1he le textContent.txt contuns un extruct lrom Shukespeure's puy \acbc|h. 1he
loowng text s the speech mude by Mucbeth shorty belore he s ked:
1o-morrow, und to-morrow, und to-morrow,
Creeps n ths petty puce lrom duy to duy,
1o the ust syube ol recorded tme,
And u our yesterduys huve ghted loos
1he wuy to u dusty deuth. Cut, out, brel cunde!
Lle's but u wukng shudow, u poor puyer,
1hut struts und lrets hs hour upon the stuge,
And then s heurd no more: t s u tue
1od by un dot, lu ol sound und lury,
Sgnlyng nothng.
1he binaryContent.doc le s u \ord document thut contuns the sume text us
textContent.txt. (A \ord document s u bnury le.) Athough u \ord document s used
n the exumpes, you cun use uny bnury le, lor exumpe, Ml3, DvX, }lLC, MlLC, lDl, or
LXL. l huve tested the exumpes wth u these types ol les.
largc Objcct Typcs
1here ure lour LC types:
CLOB 1he churucter LC type, whch s used to store churucter dutu.
NCLOB 1he Nutonu Churucter Set LC type, whch s used to store mutpe byte
churucter dutu (typcuy used lor non-Lngsh churucters). You cun eurn u ubout non-
Lngsh churucter sets n the Cracc Da|abac Coba2a|on Suppor| Cudc pubshed
by Cruce Corporuton.
BLOB 1he bnury LC type, whch s used to store bnury dutu.
BFILE 1he bnury llLL type, whch s used to store u ponter to u le. 1he le cun be
on u hurd dsk, CD, DVD, u-Ruy dsk, HD-DVD, or uny other devce thut s uccessbe
through the dutubuse server's le system. 1he le tsel s never stored n the dutubuse,
ony u ponter to the le.
lror to Cruce Dutubuse 8 your ony choce lor storng urge umounts ol dutu wus to use the
LONG und LONG RAW types (you coud uso use the RAW type lor storng bnury dutu ol ess thun
4 kobytes n sze). 1he LC types huve three udvuntuges over these oder types:
A LC cun store up to l28 terubytes ol dutu. 1hs s lur more dutu thun you cun store n
u LONG und LONG RAW coumn, whch muy ony store up to 2 ggubytes ol dutu.
A tube cun huve mutpe LC coumns, but u tube cun ony huve one LONG or LONG
RAW coumn.
LC dutu cun be uccessed n rundom order, LONG und LONG RAW dutu cun be uccessed
ony n sequentu order.
478
Cruce Dutubuse ll SQL
A LC conssts ol two purts:
Thc lOB Iucatur A ponter thut specles the ocuton ol the LC dutu
Thc lOB data 1he uctuu churucter or byte dutu stored n the LC
Dependng on the umount ol dutu stored n u CLOB, NCLOB or BLOB coumn, the dutu w be
stored ether nsde or outsde ol the tube. ll the dutu s ess thun 4 kobytes, the dutu s stored n
the sume tube, otherwse, the dutu s stored outsde the tube. \th u BFILE coumn, ony the
ocutor s stored n the tubeund the ocutor ponts to un externu le stored n the le system.
Crcating TabIcs Cuntaining largc Objccts
You' see the use ol the loowng three tubes n ths secton:
1he clob_content tube, whch contuns u CLOB coumn numed clob_column
1he blob_content tube, whch contuns u BLOB coumn numed blob_column
1he bfile_content tube, whch contuns u BFILE coumn numed bfile_column
l've provded un SQL*lus scrpt numed lob_schema.sql n the SQL drectory. 1hs scrpt
muy be run usng Cruce Dutubuse 8 und hgher. 1he scrpt creutes u user numed lob_user wth
u pussword ol lob_password, und t creutes the tubes und lL/SQL code used n the lrst purt ol
ths chupter. Alter the scrpt competes, you w be ogged n us lob_user.
1he three tubes ure creuted usng the loowng stutements n the scrpt:
CREATE TABLE clob_content (
id INTEGER PRIMARY KEY,
clob_column CLOB NOT NULL
);
CREATE TABLE blob_content (
id INTEGER PRIMARY KEY,
blob_column BLOB NOT NULL
);
CREATE TABLE bfile_content (
id INTEGER PRIMARY KEY,
bfile_column BFILE NOT NULL
);
Using largc Objccts in SQl
ln ths secton, you' eurn how to use SQL to munpuute urge obects. You' sturt by exumnng
CLOB und BLOB obects und then move on to BFILE obects.
Using ClOBs and BlOBs
1he loowng sectons show how to popuute CLOB und BLOB obects wth dutu, retreve the
dutu, und then modly the dutu.
Chupter l4: Lurge Cbects
479
PupuIating ClOBs and BlOBs with Data
1he loowng INSERT stutements udd two rows to the clob_content tube, notce the use ol
the TO_CLOB() luncton to convert the text to u CLOB:
INSERT INTO clob_content (
id, clob_column
) VALUES (
1, TO_CLOB('Creeps in this petty pace')
);
INSERT INTO clob_content (
id, clob_column
) VALUES (
2, TO_CLOB(' from day to day')
);
1he loowng INSERT stutements udd two rows to the blob_content tube, notce the
use ol the TO_BLOB() luncton to convert the numbers to u BLOB (the lrst stutement contuns
u bnury number, und the second contuns u hexudecmu number):
INSERT INTO blob_content (
id, blob_column
) VALUES (
1, TO_BLOB('100111010101011111')
);
INSERT INTO blob_content (
id, blob_column
) VALUES (
2, TO_BLOB('A0FFB71CF90DE')
);
Rctricving Data frum ClOBs
1he loowng query retreves the rows lrom the clob_content tube:
SELECT *
FROM clob_content;
ID
----------
CLOB_COLUMN
-------------------------
1
Creeps in this petty pace
2
from day to day
1he next query uttempts to retreve the row lrom the blob_content tube und lus:
SELECT *
FROM blob_content;
SP2-0678: Column or attribute type can not be displayed by SQL*Plus
480
Cruce Dutubuse ll SQL
1hs exumpe lus becuuse SQL*lus cunnot dspuy the bnury dutu n u BLOB. You' eurn how
to retreve the dutu lrom u BLOB uter n the secton Lsng Lurge Cbects n lL/SQL.
You cun, however, get the non-BLOB coumns lrom the tube:
SELECT id
FROM blob_content;
ID
----------
1
2
Mudifying thc Data in ClOBs and BlOBs
You shoud lee lree to run the UPDATE und INSERT stutements shown n ths secton. 1he
loowng UPDATE stutements show how you modly the contents ol u CLOB und u BLOB:
UPDATE clob_content
SET clob_column = TO_CLOB('What light through yonder window breaks')
WHERE id = 1;
UPDATE blob_content
SET blob_column = TO_BLOB('1110011010101011111')
WHERE id = 1;
You cun uso ntuze the LC ocutor, but not store uctuu dutu n the LC. You do ths usng the
EMPTY_CLOB() luncton to store un empty CLOB, und EMPTY_BLOB() to store un empty BLOB:
INSERT INTO clob_content(
id, clob_column
) VALUES (
3, EMPTY_CLOB()
);
INSERT INTO blob_content(
id, blob_column
) VALUES (
3, EMPTY_BLOB()
);
1hese stutements ntuze the LC ocutor, but set the LC dutu to empty.
You cun uso use EMPTY_CLOB() und EMPTY_BLOB() n UPDATE stutements when you
wunt to empty out the LC dutu. lor exumpe:
UPDATE clob_content
SET clob_column = EMPTY_CLOB()
WHERE id = 1;
UPDATE blob_content
SET blob_column = EMPTY_BLOB()
WHERE id = 1;
Chupter l4: Lurge Cbects
481
ll you run uny ol the INSERT und UPDATE stutements shown n ths secton, go uheud und ro
buck the chunges so thut your output mutches mne n the rest ol ths chupter:
ROLLBACK;
Using Bfllfs
A BFILE stores u ponter to u le thut s uccessbe through the dutubuse server's le system. 1he
mportunt pont to remember s thut these les ure stored outsde ol the dutubuse. A BFILE cun
pont to les ocuted on uny medu: u hurd dsk, CD, DVD, u-Ruy, HD-DVD, und so on.
NOTf
A BFILE con|an a pon|cr |o an cx|crna |c. Thc ac|ua |c |c|
never |orcd n |hc da|abac, on, a pon|cr |o |ha| |c |orcd. Thc
|c mu| bc acccbc |hrough |hc da|abac crvcr' |c ,|cm.
Crcating a Dircctury Objcct
elore you cun store u ponter to u le n u BFILE, you must lrst creute u drectory obect n the
dutubuse. 1he drectory obect stores the drectory n the le system where the les ure ocuted.
You creute u drectory obect usng the CREATE DIRECTORY stutement, und to run ths stutement
you must huve the CREATE ANY DIRECTORY dutubuse prvege.
1he loowng exumpe (contuned n lob_schema.sql) creutes u drectory obect numed
SAMPLE_FILES_DIR lor the le system drectory C:\sample_files:
CREATE DIRECTORY SAMPLE_FILES_DIR AS 'C:\sample_files';
NOTf
Vndov uc |hc bac|ah charac|cr (\) n drcc|orc, vhc nux
and Lnx uc |hc |orvard ah charac|cr (/). Ao, | ,our sample_
files drcc|or, no| |orcd n |hc C par||on, |hcn ,ou nccd |o
pcc|, |hc appropra|c pa|h n |hc prcvou cxampc.
\hen you creute u drectory obect you must ensure thut
1he uctuu drectory exsts n the le system.
1he user uccount n the operutng system thut wus used to nstu the Cruce soltwure hus
reud permsson on the drectory und on uny les thut ure to be ponted to by u BFILE n
the dutubuse.
ll you're usng \ndows, you shoudn't need to worry ubout the second pont. 1he Cruce
dutubuse soltwure shoud huve been nstued usng u user uccount thut hus udmnstrutor
prveges, und such u user uccount hus reud permsson on everythng n the le system. ll you're
usng Lnux or Lnx, you' need to grunt reud uccess to the upproprute Cruce user uccount thut
owns the dutubuse (you do ths usng the chmod commund).
482
Cruce Dutubuse llg SQL
PupuIating a Bfllf CuIumn with a Puintcr tu a fiIc
ecuuse u BFILE s ust u ponter to un externu le, popuutng u BFILE coumn s very smpe.
A you huve to do s to use the Cruce dutubuse's BFILENAME() luncton to popuute u BFILE
wth u ponter to your externu le. 1he BFILENAME() luncton uccepts two purumeters: the
drectory obect's nume und the nume ol the le.
lor exumpe, the loowng INSERT udds u row to the bfile_content tube, notce
thut the BFILENAME() luncton s used to popuute bfile_column wth u ponter to the
textContent.txt le:
INSERT INTO bfile_content (
id, bfile_column
) VALUES (
1, BFILENAME('SAMPLE_FILES_DIR', 'textContent.txt')
);
1he next INSERT udds u row to the bfile_content tube, notce thut the BFILENAME()
luncton s used to popuute bfile_column wth u ponter to the binaryContent.doc le:
INSERT INTO bfile_content (
id, bfile_column
) VALUES (
2, BFILENAME('SAMPLE_FILES_DIR', 'binaryContent.doc')
);
1he loowng query uttempts to retreve the rows lrom bfile_content und lus becuuse
SQL*lus cunnot dspuy the content n u BFILE:
SELECT *
FROM bfile_content;
SP2-0678: Column or attribute type can not be displayed by SQL*Plus
You muy use lL/SQL to uccess the content n u BFILE or u BLOB, und you' eurn how to do
thut next.
Using largc Objccts in Pl/SQl
ln ths secton, you' eurn how to use LCs n lL/SQL. You' sturt oll by exumnng the methods
n the DBMS_LOB puckuge, whch comes wth the dutubuse. Luter, you' see penty ol lL/SQL
progrums thut show how to use the DBMS_LOB methods to reud dutu n u LC, copy dutu lrom
one LC to unother, seurch dutu n u LC, copy dutu lrom u le to u LC, copy dutu lrom u LC
to u le, und much more.
1ube l4-l summurzes the most commony used methods n the DBMS_LOB puckuge.
ln the loowng sectons, you' see the detus ol some ol the methods shown n the prevous
tube. You cun see u the DBMS_LOB methods n the Cracc Da|abac /S ac|agc and
T,pc Rc|crcncc munuu pubshed by Cruce Corporuton.
Chupter l4: Lurge Cbects
483
Mcthud Dcscriptiun
APPEND(dest_lob, src_lob) Adds the dutu reud lrom src_lob to the end ol dest_lob.
CLOSE(lob) Coses u prevousy opened LC.
COMPARE(lob1, lob2, amount,
offset1, offset2)
Compures the dutu stored n lob1 und lob2, sturtng ut offset1 n
lob1 und offset2 n lob2. Cllsets uwuys sturt ut l, whch s the
poston ol the lrst churucter or byte n the dutu.
1he dutu n the LCs ure compured over u muxmum number ol
churucters or bytes (the muxmum s specled n amount).
CONVERTTOBLOB(dest_blob, src_clob,
amount, dest_offset, src_offset,
blob_csid, lang_context, warning)
Converts the churucter dutu reud lrom src_clob nto bnury dutu
wrtten to dest_blob.
1he reud begns ut src_offset n src_clob, und the wrte begns
ut dest_offset n dest_blob.
blob_csid s the desred churucter set lor the converted dutu wrtten
to dest_blob. You shoud typcuy use DBMS_LOB.DEFAULT_
CSID, whch s the deluut churucter set lor the dutubuse.
lang_context s the unguuge context to use when convertng the
churucters reud lrom src_clob. You shoud typcuy use DBMS_
LOB.DEFAULT_LANG_CTX, whch s the deluut unguuge context lor
the dutubuse.
warning s set to DBMS_LOB.WARN_INCONVERTIBLE_CHAR l
there wus u churucter thut coud not be converted.
CONVERTTOCLOB(dest_clob, src_blob,
amount, dest_offset, src_offset,
blob_csid, lang_context, warning)
Converts the bnury dutu reud lrom src_blob nto churucter dutu
wrtten to dest_clob.
blob_csid s the churucter set lor the dutu reud lrom dest_blob.
You shoud typcuy use DBMS_LOB.DEFAULT_CSID.
lang_context s the unguuge context to use when wrtng the
converted churucters to dest_clob. You shoud typcuy use DBMS_
LOB.DEFAULT_LANG_CTX.
warning s set to DBMS_LOB.WARN_INCONVERTIBLE_CHAR l
there wus u churucter thut coud not be converted.
COPY(dest_lob, src_lob, amount,
dest_offset, src_offset)
Copes dutu lrom src_lob to dest_lob, sturtng ut the ollsets lor u
totu umount ol churucters or bytes.
CREATETEMPORARY(lob, cache,
duration)
Creutes u temporury LC n the user's deluut temporury tubespuce.
ERASE(lob, amount, offset) Lruses dutu lrom u LC, sturtng ut the ollset lor u totu umount ol
churucters or bytes.
FILECLOSE(bfile) Coses bfile. You shoud use the newer CLOSE() method nsteud ol
FILECLOSE().
FILECLOSEALL() Coses u prevousy opened BFILEs.
FILEEXISTS(bfile)
Checks l the externu le ponted to by bfile uctuuy exsts.
FILEGETNAME(bfile, directory,
filename)
Returns the drectory und lenume ol the externu le ponted to by
bfile.
FILEISOPEN(bfile)
Checks l bfile s currenty open. You shoud use the newer
ISOPEN() method nsteud ol FILEISOPEN().
FILEOPEN(bfile, open_mode) Cpens bfile n the ndcuted mode, whch cun be set ony to
DBMS_LOB.FILE_READONLY, whch ndcutes the le muy ony be
reud lrom (und never wrtten to). You shoud use the newer OPEN()
method nsteud ol FILEOPEN().
TABlf 14-1 DBMS_LOB
484
Cruce Dutubuse llg SQL
Mcthud Dcscriptiun
FREETEMPORARY(lob)
lrees u temporury LC.
GETCHUNKSIZE(lob) Returns the chunk sze used when reudng und wrtng the dutu stored
n the LC. A chunk s u unt ol dutu.
GET_STORAGE_LIMIT() Returns the muxmum uowube sze lor u LC.
GETLENGTH(lob)
Cets the ength ol the dutu stored n the LC.
INSTR(lob, pattern, offset, n) Returns the sturtng poston ol churucters or bytes thut mutch the n|h
occurrence ol u puttern n the LC dutu. 1he dutu s reud lrom the
LC sturtng ut the ollset.
ISOPEN(lob) Checks l the LC wus ureudy opened.
ISTEMPORARY(lob)
Checks l the LC s u temporury LC.
LOADFROMFILE(dest_lob, src_bfile,
amount, dest_offset, src_offset)
Louds the dutu retreved vu src_bfile to dest_lob, sturtng ut
the ollsets lor u totu umount ol churucters or bytes, src_bfile s u
BFILE thut ponts to un externu le.
LOADFROMFILE() s od, und you shoud use the hgher-
perlormunce LOADBLOBFROMFILE() or LOADCLOBFROMFILE()
methods.
LOADBLOBFROMFILE(dest_blob,
src_bfile, amount, dest_offset,
src_offset)
Louds the dutu retreved vu src_bfile to dest_blob, sturtng ut
the ollsets lor u totu umount ol bytes, src_bfile s u BFILE thut
ponts to un externu le.
LOADBLOBFROMFILE() ollers mproved perlormunce over
LOADFROMFILE() when usng u BLOB.
LOADCLOBFROMFILE(dest_clob, src_
bfile, amount, dest_offset, src_
offset, src_csid, lang_context,
warning)
Louds the dutu retreved vu src_bfile to dest_clob, sturtng ut
the ollsets lor u totu umount ol churucters, src_bfile s u BFILE
thut ponts to un externu le.
LOADCLOBFROMFILE() ollers mproved perlormunce over
LOADFROMFILE() when usng u CLOB/NCLOB.
LOBMAXSIZE
Returns the muxmum sze lor u LC n bytes (currenty 2
64
).
OPEN(lob, open_mode) Cpens the LC n the ndcuted mode, whch muy be set to
DBMS_LOB.FILE_READONLY, whch ndcutes the LC muy ony
be reud lrom
DBMS_LOB.FILE_READWRITE, whch ndcutes the LC muy
reud lrom und wrtten to
READ(lob, amount, offset, buffer) Reuds the dutu lrom the LC und stores them n the buffer vurube,
sturtng ut the ollset n the LC lor u totu umount ol churucters or bytes.
SUBSTR(lob, amount, offset) Returns purt ol the LC dutu, sturtng ut the ollset n the LC lor u
totu umount ol churucters or bytes.
TRIM(lob, newlen) 1rms the LC dutu to the specled shorter ength.
WRITE(lob, amount, offset, buffer) \rtes the dutu lrom the buffer vurube to the LC, sturtng ut the
ollset n the LC lor u totu umount ol churucters or bytes.
WRITEAPPEND(lob, amount, buffer) \rtes the dutu lrom the buffer vurube to the end ol the LC,
sturtng ut the ollset n the LC lor u totu umount ol churucters or bytes.
TABlf 14-1 DBMS_LOB \c|hod (contnued)
Chupter l4: Lurge Cbects
48S
APPfND()
APPEND() udds the dutu n u source LC to the end ol u destnuton LC. 1here ure two versons
ol APPEND():
DBMS_LOB.APPEND(
dest_lob IN OUT NOCOPY BLOB,
src_lob IN BLOB
);
DBMS_LOB.APPEND(
dest_lob IN OUT NOCOPY CLOB/NCLOB CHARACTER SET ANY_CS,
src_lob IN CLOB/NCLOB CHARACTER SET dest_lob%CHARSET
);
where
dest_lob s the destnuton LC to whch the dutu s uppended.
src_lob s the source LC lrom whch the dutu s reud.
CHARACTER SET ANY_CS meuns the dutu n dest_lob cun be uny churucter set.
CHARACTER SET dest_lob%CHARSET s the churucter set ol dest_lob.
1he loowng tube shows the excepton thrown by APPEND().
fxccptiun Thruwn Whcn
VALUE_ERROR
Lther dest_lob or src_lob s nu.
ClOSf()
CLOSE() coses u prevousy opened LC. 1here ure three versons ol CLOSE():
DBMS_LOB.CLOSE(
lob IN OUT NOCOPY BLOB
);
DBMS_LOB.CLOSE(
lob IN OUT NOCOPY CLOB/NCLOB CHARACTER SET ANY_CS
);
DBMS_LOB.CLOSE(
lob IN OUT NOCOPY BFILE
);
wherelob s the LC to be cosed.
486
Cruce Dutubuse ll SQL
COMPARf()
COMPARE() compures the dutu stored n two LCs, sturtng ut the ollsets over u totu umount ol
churucters or bytes. 1here ure three versons ol COMPARE():
DBMS_LOB.COMPARE(
lob1 IN BLOB,
lob2 IN BLOB,
amount IN INTEGER := 4294967295,
offset1 IN INTEGER := 1,
offset2 IN INTEGER := 1
) RETURN INTEGER;
DBMS_LOB.COMPARE(
lob1 IN CLOB/NCLOB CHARACTER SET ANY_CS,
lob2 IN CLOB/NCLOB CHARACTER SET lob_1%CHARSET,
amount IN INTEGER := 4294967295,
offset1 IN INTEGER := 1,
offset2 IN INTEGER := 1
) RETURN INTEGER;
DBMS_LOB.COMPARE(
lob1 IN BFILE,
lob2 IN BFILE,
amount IN INTEGER,
offset1 IN INTEGER := 1,
offset2 IN INTEGER := 1
) RETURN INTEGER;
where
lob1 und lob2 ure the LCs to compure.
amount s the muxmum number ol churucters to reud lrom u CLOB/NCLOB, or the
muxmum number ol bytes to reud lrom u BLOB/BFILE.
offset1 und offset2 ure the ollsets n churucters or bytes n lob1 und lob2 to sturt
the compurson (the ollsets sturt ut l).
COMPARE() returns
0 l the LCs ure dentcu.
l l the LCs uren't dentcu.
Nu l
amount < 1
amount > LOBMAXSIZE (Note: LOBMAXSIZE s the muxmum sze ol the LC)
offset1 or offset2 < 1
offset1 or offset2 > LOBMAXSIZE
Chupter l4: Lurge Cbects
487
1he loowng tube shows the exceptons thrown by COMPARE().
fxccptiun Thruwn Whcn
UNOPENED_FILE
1he le husn't been opened yet.
NOEXIST_DIRECTORY
1he drectory doesn't exst.
NOPRIV_DIRECTORY
You don't huve prveges to uccess the drectory.
INVALID_DIRECTORY
1he drectory s nvud.
INVALID_OPERATION
1he le exsts, but you don't huve prveges to uccess the le.
COPY()
COPY() copes dutu lrom u source LC to u destnuton LC, sturtng ut the ollsets lor u totu
umount ol churucters or bytes. 1here ure two versons ol COPY():
DBMS_LOB.COPY(
dest_lob IN OUT NOCOPY BLOB,
src_lob IN BLOB,
amount IN INTEGER,
dest_offset IN INTEGER := 1,
src_offset IN INTEGER := 1
);
DBMS_LOB.COPY(
dest_lob IN OUT NOCOPY CLOB/NCLOB CHARACTER SET ANY_CS,
src_lob IN CLOB/NCLOB CHARACTER SET dest_lob%CHARSET,
amount IN INTEGER,
dest_offset IN INTEGER := 1,
src_offset IN INTEGER := 1
);
where
dest_lob und src_lob ure the LCs to wrte to und reud lrom, respectvey.
amount s the muxmum number ol churucters to reud lrom u CLOB/NCLOB, or the
muxmum number ol bytes to reud lrom u BLOB/BFILE.
dest_offset und src_offset ure the ollsets n churucters or bytes n dest_lob und
src_lob to sturt the copy (the ollsets sturt ut l).
1he loowng tube shows the exceptons thrown by COPY().
fxccptiun Thruwn Whcn
VALUE_ERROR
Any ol the purumeters ure nu.
INVALID_ARGVAL
Lther:
src_offset < 1
dest_offset < 1
src_offset > LOBMAXSIZE
dest_offset > LOBMAXSIZE
amount < 1
amount > LOBMAXSIZE
488
Cruce Dutubuse ll SQL
CRfATfTfMPORARY()
CREATETEMPORARY() creutes u temporury LC n the user's deluut temporury tubespuce.
1here ure two versons ol CREATETEMPORARY():
DBMS_LOB.CREATETEMPORARY(
lob IN OUT NOCOPY BLOB,
cache IN BOOLEAN,
duration IN PLS_INTEGER := 10
);
DBMS_LOB.CREATETEMPORARY (
lob IN OUT NOCOPY CLOB/NCLOB CHARACTER SET ANY_CS,
cache IN BOOLEAN,
duration IN PLS_INTEGER := 10
);
where
lob s the temporury LC to creute.
cache ndcutes whether the LC shoud be reud nto the buller cuche (true lor yes, luse
lor no).
duration s u hnt (cun be set to SESSION, TRANSACTION, or CALL) us to whether the
temporury LC s removed ut the end ol the sesson, trunsucton, or cu (the deluut s
SESSION).
1he loowng tube shows the excepton thrown by CREATETEMPORARY().
fxccptiun Thruwn Whcn
VALUE_ERROR
1he lob purumeter s nu.
fRASf()
ERASE() removes dutu lrom u LC, sturtng ut the ollset lor u totu umount ol churucters or bytes.
1here ure two versons ol ERASE():
DBMS_LOB.ERASE(
lob IN OUT NOCOPY BLOB,
amount IN OUT NOCOPY INTEGER,
offset IN INTEGER := 1
);
DBMS_LOB.ERASE(
lob IN OUT NOCOPY CLOB/NCLOB CHARACTER SET ANY_CS,
amount IN OUT NOCOPY INTEGER,
offset IN INTEGER := 1
);
where
lob s the LC to eruse.
Chupter l4: Lurge Cbects
489
amount s the muxmum number ol churucters to reud lrom u CLOB/NCLOB, or the
number ol bytes to reud lrom u BLOB.
offset s the ollset n churucters or bytes n lob to sturt the erusure (the ollset sturts ut l).
1he loowng tube shows the exceptons thrown by ERASE().
fxccptiun Thruwn Whcn
VALUE_ERROR
Any ol the purumeters ure nu.
INVALID_ARGVAL
Lther:
amount < 1
amount > LOBMAXSIZE
offset < 1
offset > LOBMAXSIZE
fllfClOSf()
FILECLOSE() coses u BFILE. You shoud use the newer CLOSE() procedure, us Cruce
Corporuton does not pun to extend the oder FILECLOSE() procedure. l'm ony ncudng
coveruge ol FILECLOSE() here so you cun understund oder progrums.
DBMS_LOB.FILECLOSE(
bfile IN OUT NOCOPY BFILE
);
wherebfile s the BFILE to cose.
1he loowng tube shows the exceptons thrown by FILECLOSE().
fxccptiun Thruwn Whcn
VALUE_ERROR
1he bfile purumeter s nu.
UNOPENED_FILE
1he le husn't been opened yet.
NOEXIST_DIRECTORY
1he drectory doesn't exst.
NOPRIV_DIRECTORY
You don't huve prveges to uccess the drectory.
INVALID_DIRECTORY
1he drectory s nvud.
INVALID_OPERATION
1he le exsts, but you don't huve prveges to uccess the le.
fllfClOSfAll()
FILECLOSEALL() coses u BFILE obects.
DBMS_LOB.FILECLOSEALL;
1he loowng tube shows the excepton thrown by FILECLOSEALL().
fxccptiun Thruwn Whcn
UNOPENED_FILE
No les huve been opened n the sesson.
490
Cruce Dutubuse ll SQL
fllffXlSTS()
FILEEXISTS() checks l u le exsts.
DBMS_LOB.FILEEXISTS(
bfile IN BFILE
) RETURN INTEGER;
wherebfile s u BFILE thut ponts to un externu le.
FILEEXISTS() returns
0 l the le doesn't exst.
l l the le exsts.
1he loowng tube shows the exceptons thrown by FILEEXISTS().
fxccptiun Thruwn Whcn
VALUE_ERROR
1he bfile purumeter s nu.
NOEXIST_DIRECTORY
1he drectory doesn't exst.
NOPRIV_DIRECTORY
You don't huve prveges to uccess the drectory.
INVALID_DIRECTORY
1he drectory s nvud.
fllfGfTNAMf()
FILEGETNAME() returns the drectory und lenume lrom u BFILE.
DBMS_LOB.FILEGETNAME(
bfile IN BFILE,
directory OUT VARCHAR2,
filename OUT VARCHAR2
);
where
bfile s the ponter to the le.
directory s the drectory where the le s stored.
filename s the nume ol the le.
1he loowng tube shows the exceptons thrown by FILEGETNAME().
fxccptiun Thruwn Whcn
VALUE_ERROR
Any ol the nput purumeters ure nu or nvud.
INVALID_ARGVAL
1he directory or filename purumeters ure nu.
fllflSOPfN()
FILEISOPEN() checks l u le s open. You shoud use the newer ISOPEN() procedure to
check l u le s open n your own progrums, us Cruce Corporuton does not pun to extend the
oder FILEISOPEN() method. l'm ncudng coveruge ol FILEISOPEN() here ony so you cun
understund oder progrums.
Chupter l4: Lurge Cbects
491
DBMS_LOB.FILEISOPEN(
bfile IN BFILE
) RETURN INTEGER;
where bfile s the ponter to the le.
FILEISOPEN() returns
0 l the le sn't open.
l l the le s open.
1he loowng tube shows the exceptons thrown by FILEISOPEN().
fxccptiun Thruwn Whcn
NOEXIST_DIRECTORY
1he drectory doesn't exst.
NOPRIV_DIRECTORY
You don't huve prveges to uccess the drectory.
INVALID_DIRECTORY
1he drectory s nvud.
INVALID_OPERATION
1he le doesn't exst or you don't huve prveges to uccess the le.
fllfOPfN()
FILEOPEN() opens u le. You shoud use the newer OPEN() procedure to open u le n your
own progrums, us Cruce Corporuton does not pun to extend the oder FILEOPEN() procedure.
l'm ncudng coveruge ol FILEOPEN() here ony so you cun understund oder progrums.
DBMS_LOB.FILEOPEN(
bfile IN OUT NOCOPY BFILE,
open_mode IN BINARY_INTEGER := DBMS_LOB.FILE_READONLY
);
where
bfile s the ponter to the le.
open_mode ndcutes the open mode, the ony open mode s DBMS_LOB.FILE_
READONLY, whch ndcutes the le muy be reud lrom.
1he loowng tube shows the exceptons thrown by FILEOPEN().
fxccptiun Thruwn Whcn
VALUE_ERROR
Any ol the nput purumeters ure nu or nvud.
INVALID_ARGVAL
1he open_mode s not set to DBMS_LOB.FILE_READONLY
OPEN_TOOMANY
An uttempt wus mude to open more thun SESSION_MAX_OPEN_
FILES les, where SESSION_MAX_OPEN_FILES s u dutubuse
ntuzuton purumeter set by u dutubuse udmnstrutor.
NOEXIST_DIRECTORY
1he drectory doesn't exst.
INVALID_DIRECTORY
1he drectory s nvud.
INVALID_OPERATION
1he le exsts, but you don't huve prveges to uccess the le.
492
Cruce Dutubuse ll SQL
fRffTfMPORARY()
FREETEMPORARY() lrees u temporury LC lrom the deluut temporury tubespuce ol the user.
1here ure two versons ol FREETEMPORARY():
DBMS_LOB.FREETEMPORARY (
lob IN OUT NOCOPY BLOB
);
DBMS_LOB.FREETEMPORARY (
lob IN OUT NOCOPY CLOB/NCLOB CHARACTER SET ANY_CS
);
where lob s the ob to be lreed.
1he loowng tube shows the excepton thrown by FREETEMPORARY().
fxccptiun Thruwn Whcn
VALUE_ERROR
Any ol the nput purumeters ure nu or nvud.
GfTCHUNkSlZf()
GETCHUNKSIZE() returns the chunk sze when reudng und wrtng LC dutu (u chunk s u unt
ol dutu). 1here ure two versons ol GETCHUNKSIZE():
DBMS_LOB.GETCHUNKSIZE(
lob IN BLOB
) RETURN INTEGER;
DBMS_LOB.GETCHUNKSIZE(
lob IN CLOB/NCLOB CHARACTER SET ANY_CS
) RETURN INTEGER;
wherelob s the LC to get the chunk sze lor.
GETCHUNKSIZE() returns
1he chunk sze n bytes lor u BLOB
1he chunk sze n churucters lor u CLOB/NCLOB
1he loowng tube shows the excepton thrown by GETCHUNKSIZE().
fxccptiun Thruwn Whcn
VALUE_ERROR
1he lob purumeter s nu.
GfT_STORAGf_llMlT()
GET_STORAGE_LIMIT() returns the muxmum uowube sze lor u LC.
DBMS_LOB.GET_STORAGE_LIMIT()
RETURN INTEGER;
Chupter l4: Lurge Cbects
493
GfTlfNGTH()
GETLENGTH() returns the ength ol the LC dutu. 1here ure three versons ol GETLENGTH():
DBMS_LOB.GETLENGTH(
lob IN BLOB
) RETURN INTEGER;
DBMS_LOB.GETLENGTH(
lob IN CLOB/NCLOB CHARACTER SET ANY_CS
) RETURN INTEGER;
DBMS_LOB.GETLENGTH(
bfile IN BFILE
) RETURN INTEGER;
where
lob s the BLOB, CLOB, or NCLOB dutu to get the ength ol.
bfile s the BFILE dutu to get the ength ol.
GETLENGTH() returns
1he ength n bytes lor u BLOB or BFILE
1he ength n churucters lor u CLOB or NCLOB
1he loowng tube shows the excepton thrown by GETLENGTH().
fxccptiun Thruwn Whcn
VALUE_ERROR
1he lob or bfile purumeter s nu.
lNSTR()
INSTR() returns the sturtng poston ol churucters thut mutch the occurrence ol u puttern n
the LC dutu, sturtng ut un ollset. 1here ure three versons ol INSTR():
DBMS_LOB.INSTR(
lob IN BLOB,
pattern IN RAW,
offset IN INTEGER := 1,
n IN INTEGER := 1
) RETURN INTEGER;
DBMS_LOB.INSTR(
lob IN CLOB/NCLOB CHARACTER SET ANY_CS,
pattern IN VARCHAR2 CHARACTER SET lob%CHARSET,
offset IN INTEGER := 1,
n IN INTEGER := 1
) RETURN INTEGER;
494
Cruce Dutubuse ll SQL
DBMS_LOB.INSTR(
bfile IN BFILE,
pattern IN RAW,
offset IN INTEGER := 1,
n IN INTEGER := 1
) RETURN INTEGER;
where
lob s the BLOB, CLOB, or NCLOB to reud lrom.
bfile s the BFILE to reud lrom.
pattern s the puttern to seurch lor n the LC dutu, the puttern s u group ol RAW bytes
lor u BLOB or BFILE, und u VARCHAR2 churucter strng lor u CLOB, the muxmum sze ol
the puttern s l6,383 bytes.
offset s the ollset to sturt reudng dutu lrom the LC (the ollset sturts ut l).
n s the occurrence ol the puttern to seurch the dutu lor.
INSTR() returns
1he ollset ol the sturt ol the puttern (l lound)
Zero l the puttern sn't lound
Nu l
Any ol the IN purumeters ure nu or nvud
offset < 1 or offset > LOBMAXSIZE
n < l or n > LOBMAXSIZE
1he loowng tube shows the exceptons thrown by INSTR().
fxccptiun Thruwn Whcn
VALUE_ERROR
Any ol the nput purumeters ure nu or nvud.
UNOPENED_FILE
1he BFILE sn't open.
NOEXIST_DIRECTORY
1he drectory doesn't exst.
NOPRIV_DIRECTORY
1he drectory exsts, but you don't huve prveges to uccess the
drectory.
INVALID_DIRECTORY
1he drectory s nvud.
INVALID_OPERATION
1he le exsts, but you don't huve prveges to uccess the le.
lSOPfN()
ISOPEN() checks l the LC wus ureudy opened. 1here ure three versons ol ISOPEN():
Chupter l4: Lurge Cbects
49S
DBMS_LOB.ISOPEN(
lob IN BLOB
) RETURN INTEGER;
DBMS_LOB.ISOPEN(
lob IN CLOB/NCLOB CHARACTER SET ANY_CS
) RETURN INTEGER;
DBMS_LOB.ISOPEN(
bfile IN BFILE
) RETURN INTEGER;
where
lob s the BLOB, CLOB, or NCLOB to check.
bfile s the BFILE to check.
ISOPEN() returns
0 l the LC sn't open.
l l the LC s open.
1he loowng tube shows the excepton thrown by ISOPEN().
fxccptiun Thruwn Whcn
VALUE_ERROR
1he lob or bfile purumeter s nu or nvud.
lSTfMPORARY()
ISTEMPORARY() checks l the LC s u temporury LC. 1here ure two versons ol
ISTEMPORARY():
DBMS_LOB.ISTEMPORARY(
lob IN BLOB
) RETURN INTEGER;
DBMS_LOB.ISTEMPORARY (
lob IN CLOB/NCLOB CHARACTER SET ANY_CS
) RETURN INTEGER;
where
lob s the LC to check.
ISTEMPORARY() returns
0 l the LC sn't temporury.
l l the LC s temporury.
496
Cruce Dutubuse ll SQL
1he loowng tube shows the excepton thrown by ISTEMPORARY().
fxccptiun Thruwn Whcn
VALUE_ERROR
1he lob purumeter s nu or nvud.
lOADfROMfllf()
LOADFROMFILE() ouds dutu retreved vu u BFILE nto u CLOB, NCLOB, or BLOB, sturtng ut the
ollsets lor u totu umount ol churucters or bytes. You shoud use the hgher-perlormunce
LOADCLOBFROMFILE() or LOADBLOBFROMFILE() procedures n your own progrums, und l'm
ncudng coveruge ol LOADFROMFILE() here ony so you cun understund oder progrums.
1here ure two versons ol LOADFROMFILE():
DBMS_LOB.LOADFROMFILE(
dest_lob IN OUT NOCOPY BLOB,
src_bfile IN BFILE,
amount IN INTEGER,
dest_offset IN INTEGER := 1,
src_offset IN INTEGER := 1
);
DBMS_LOB.LOADFROMFILE(
dest_lob IN OUT NOCOPY CLOB/NCLOB CHARACTER SET ANY_CS,
src_bfile IN BFILE,
amount IN INTEGER,
dest_offset IN INTEGER := 1,
src_offset IN INTEGER := 1
);
where
dest_lob s the LC nto whch the dutu s to be wrtten.
src_bfile s the ponter to the le lrom whch the dutu s to be reud.
amount s the muxmum number ol bytes or churucters to reud lrom src_bfile.
dest_offset s the ollset n bytes or churucters n dest_lob to sturt wrtng dutu (the
ollset sturts ut l).
src_offset s the ollset n bytes n src_bfile to sturt reudng dutu (the ollset sturts ut l).
1he loowng tube shows the exceptons thrown by LOADFROMFILE().
fxccptiun Thruwn Whcn
VALUE_ERROR
Any ol the nput purumeters ure nu or nvud.
INVALID_ARGVAL
Lther:
src_offset < 1
dest_offset < 1
src_offset > LOBMAXSIZE
dest_offset > LOBMAXSIZE
amount < 1
amount > LOBMAXSIZE
Chupter l4: Lurge Cbects
497
lOADBlOBfROMfllf()
LOADBLOBFROMFILE() ouds dutu retreved vu u BFILE nto u BLOB. LOADBLOBFROMFILE()
ollers mproved perlormunce over the LOADFROMFILE() method when usng u BLOB.
DBMS_LOB.LOADBLOBFROMFILE(
dest_blob IN OUT NOCOPY BLOB,
src_bfile IN BFILE,
amount IN INTEGER,
dest_offset IN OUT INTEGER := 1,
src_offset IN OUT INTEGER := 1
);
where
dest_blob s the BLOB nto whch the dutu s to be wrtten.
src_bfile s the ponter to the le lrom whch the dutu s to be reud.
amount s the muxmum number ol bytes to reud lrom src_bfile.
dest_offset s the ollset n bytes n dest_lob to sturt wrtng dutu (the ollset sturts
ut l).
src_offset s the ollset n bytes n src_bfile to sturt reudng dutu (the ollset sturts
ut l).
1he loowng tube shows the exceptons thrown by LOADBLOBFROMFILE().
fxccptiun Thruwn Whcn
VALUE_ERROR
Any ol the nput purumeters ure nu or nvud.
INVALID_ARGVAL
Lther:
src_offset < 1
dest_offset < 1
src_offset > LOBMAXSIZE
dest_offset > LOBMAXSIZE
amount < 1
amount > LOBMAXSIZE
lOADClOBfROMfllf()
LOADCLOBFROMFILE() ouds dutu retreved vu u BFILE nto u CLOB/NCLOB.
LOADCLOBFROMFILE() ollers mproved perlormunce over the LOADFROMFILE()
method when usng u CLOB/NCLOB. LOADCLOBFROMFILE() uso uutomutcuy converts
bnury dutu to churucter dutu.
DBMS_LOB.LOADCLOBFROMFILE(
dest_clob IN OUT NOCOPY CLOB/NCLOB,
src_bfile IN BFILE,
amount IN INTEGER,
dest_offset IN OUT INTEGER,
src_offset IN OUT INTEGER,
src_csid IN NUMBER,
498
Cruce Dutubuse llg SQL
lang_context IN OUT INTEGER,
warning OUT INTEGER
);
where
dest_blob s the CLOB/NCLOB nto whch the dutu s to be wrtten.
src_bfile s the ponter to the le lrom whch the dutu s to be reud.
amount s the muxmum number ol churucters to reud lrom src_bfile.
dest_offset s the ollset n churucters n dest_lob to sturt wrtng dutu (the ollset
sturts ut l).
src_offset s the ollset n churucters n src_bfile to sturt reudng dutu (the ollset
sturts ut l).
src_csid s the churucter set ol src_bfile (you shoud typcuy use DBMS_LOB
.DEFAULT_CSID, whch s the deluut churucter set lor the dutubuse).
lang_context s the unguuge context to use lor the oud (you shoud typcuy
use DBMS_LOB.DEFAULT_LANG_CTX, whch s the deluut unguuge context lor the
dutubuse).
warning s u wurnng messuge thut contuns nlormuton l there wus u probem wth
the oud, u common probem s thut u churucter n src_bfile cunnot be converted
to u churucter n dest_lob (n whch cuse, warning s set to DBMS_LOB.WARN_
INCONVERTIBLE_CHAR).
NOTf
You can carn a abou| charac|cr c|, con|cx|, and hov |o convcr|
charac|cr |rom onc anguagc |o ano|hcr n |hc Cruce Dutubuse
Cobuzuton Support Cude pubhcd b, Cracc Corpora|on.
1he loowng tube shows the exceptons thrown by LOADCLOBFROMFILE().
fxccptiun Thruwn Whcn
VALUE_ERROR
Any ol the nput purumeters ure nu or nvud.
INVALID_ARGVAL
Lther:
src_offset < 1
dest_offset < 1
src_offset > LOBMAXSIZE
dest_offset > LOBMAXSIZE
amount < 1
amount > LOBMAXSIZE
OPfN()
OPEN() opens u LC. 1here ure three versons ol OPEN():
Chupter l4: Lurge Cbects
499
DBMS_LOB.OPEN(
lob IN OUT NOCOPY BLOB,
open_mode IN BINARY_INTEGER
);
DBMS_LOB.OPEN(
lob IN OUT NOCOPY CLOB/NCLOB CHARACTER SET ANY_CS,
open_mode IN BINARY_INTEGER
);
DBMS_LOB.OPEN(
bfile IN OUT NOCOPY BFILE,
open_mode IN BINARY_INTEGER := DBMS_LOB.FILE_READONLY
);
where
lob s the LC to open.
bfile s the ponter to the le to open.
open_mode ndcutes the open mode, the deluut s DBMS_LOB.FILE_READONLY,
whch ndcutes the LC muy ony be reud lrom, DBMS_LOB.FILE_READWRITE
ndcutes the LC muy be reud lrom und wrtten to.
1he loowng tube shows the excepton thrown by OPEN().
fxccptiun Thruwn Whcn
VALUE_ERROR
Any ol the nput purumeters ure nu or nvud.
RfAD()
READ() reuds dutu nto u buller lrom u LC. 1here ure three versons ol READ():
DBMS_LOB.READ(
lob IN BLOB,
amount IN OUT NOCOPY BINARY_INTEGER,
offset IN INTEGER,
buffer OUT RAW
);
DBMS_LOB.READ(
lob IN CLOB/NCLOB CHARACTER SET ANY_CS,
amount IN OUT NOCOPY BINARY_INTEGER,
offset IN INTEGER,
buffer OUT VARCHAR2 CHARACTER SET lob%CHARSET
);
DBMS_LOB.READ(
bfile IN BFILE,
amount IN OUT NOCOPY BINARY_INTEGER,
S00
Cruce Dutubuse ll SQL
offset IN INTEGER,
buffer OUT RAW
);
where
lob s the CLOB, NCLOB, or BLOB to reud lrom.
bfile s the BFILE to reud lrom.
amount s the muxmum number ol churucters to reud lrom u CLOB/NCLOB, or the
muxmum number ol bytes to reud lrom u BLOB/BFILE.
offset s the ollset to sturt reudng (the ollset sturts ut l).
buffer s the vurube where the dutu reud lrom the LC s to be stored.
1he loowng tube shows the exceptons thrown by READ().
fxccptiun Thruwn Whcn
VALUE_ERROR
Any ol the nput purumeters ure nu.
INVALID_ARGVAL
Lther:
amount < 1
amount > MAXBUFSIZE
amount > cupucty ol buller n bytes or churucters
offset < 1
offset > LOBMAXSIZE
NO_DATA_FOUND
1he end ol the LC wus reuched und there ure no more bytes or
churucters to reud lrom the LC.
SUBSTR()
SUBSTR() returns purt ol the LC dutu, sturtng ut the ollset lor u totu umount ol churucters or
bytes. 1here ure three versons ol SUBSTR():
DBMS_LOB.SUBSTR(
lob IN BLOB,
amount IN INTEGER := 32767,
offset IN INTEGER := 1
) RETURN RAW;
DBMS_LOB.SUBSTR (
lob IN CLOB/NCLOB CHARACTER SET ANY_CS,
amount IN INTEGER := 32767,
offset IN INTEGER := 1
) RETURN VARCHAR2 CHARACTER SET lob%CHARSET;
DBMS_LOB.SUBSTR (
bfile IN BFILE,
amount IN INTEGER := 32767,
offset IN INTEGER := 1
) RETURN RAW;
Chupter l4: Lurge Cbects
S01
where
lob s the BLOB, CLOB, or NCLOB to reud lrom.
bfile s the ponter to the le to reud lrom.
amount s the muxmum number ol churucters reud lrom u CLOB/NCLOB, or the
muxmum number ol bytes to reud lrom u BLOB/BFILE.
offset s the ollset to sturt reudng dutu lrom the LC (the ollset sturts ut l).
SUBSTR() returns
RAW dutu when reudng lrom u BLOB/BFILE.
VARCHAR2 dutu when reudng lrom u CLOB/NCLOB.
Nu l
amount < 1
amount > 32767
offset < 1
offset > LOBMAXSIZE
1he loowng tube shows the exceptons thrown by SUBSTR().
fxccptiun Thruwn Whcn
VALUE_ERROR
Any ol the nput purumeters ure nu or nvud.
UNOPENED_FILE
1he BFILE sn't open.
NOEXIST_DIRECTORY
1he drectory doesn't exst.
NOPRIV_DIRECTORY
You don't huve prveges on the drectory.
INVALID_DIRECTORY
1he drectory s nvud.
INVALID_OPERATION
1he le exsts, but you don't huve prveges to uccess the le.
TRlM()
TRIM() trms the LC dutu to the specled shorter ength. 1here ure two versons ol TRIM():
DBMS_LOB.TRIM(
lob IN OUT NOCOPY BLOB,
newlen IN INTEGER
);
DBMS_LOB.TRIM(
lob IN OUT NOCOPY CLOB/NCLOB CHARACTER SET ANY_CS,
newlen IN INTEGER
);
where
S02
Cruce Dutubuse ll SQL
lob s the BLOB, CLOB, or NCLOB to trm.
newlen s the new ength (n bytes lor u BLOB, or churucters lor u CLOB/NCLOB).
1he loowng tube shows the exceptons thrown by TRIM().
fxccptiun Thruwn Whcn
VALUE_ERROR
1he ob purumeter s nu.
INVALID_ARGVAL
Lther:
newlen < 0
newlen > LOBMAXSIZE
WRlTf()
WRITE() wrtes dutu lrom u buller to u LC. 1here ure two versons ol WRITE():
DBMS_LOB.WRITE(
lob IN OUT NOCOPY BLOB,
amount IN BINARY_INTEGER,
offset IN INTEGER,
buffer IN RAW
);
DBMS_LOB.WRITE(
lob IN OUT NOCOPY CLOB/NCLOB CHARACTER SET ANY_CS,
amount IN BINARY_INTEGER,
offset IN INTEGER,
buffer IN VARCHAR2 CHARACTER SET lob%CHARSET
);
where
lob s the LC to wrte to.
amount s the muxmum number ol churucters to wrte to u CLOB/NCLOB, or the
muxmum number ol bytes to wrte to u BLOB.
offset s the ollset to sturt wrtng dutu to the LC (the ollset sturts ut l).
buffer s the vurube thut contuns the dutu to be wrtten to the LC.
1he loowng tube shows the exceptons thrown by WRITE().
fxccptiun Thruwn Whcn
VALUE_ERROR
Any ol the nput purumeters ure nu or nvud.
INVALID_ARGVAL
Lther:
amount < 1
amount > MAXBUFSIZE
offset < 1
offset > LOBMAXSIZE
Chupter l4: Lurge Cbects
S03
WRlTfAPPfND()
WRITEAPPEND() wrtes dutu lrom the buller to the end ol u LC, sturtng ut the ollset lor u totu
umount ol churucters or bytes. 1here ure two versons ol WRITEAPPEND():
DBMS_LOB.WRITEAPPEND(
lob IN OUT NOCOPY BLOB,
amount IN BINARY_INTEGER,
buffer IN RAW
);
DBMS_LOB.WRITEAPPEND(
lob IN OUT NOCOPY CLOB/NCLOB CHARACTER SET ANY_CS,
amount IN BINARY_INTEGER,
buffer IN VARCHAR2 CHARACTER SET lob%CHARSET
);
where
lob s the BLOB, CLOB, or NCLOB to wrte to.
amount s the muxmum number ol churucters to wrte to u CLOB/NCLOB, or the
muxmum number ol bytes to wrte to u BLOB.
buffer s the vurube thut contuns the dutu to be wrtten to the LC.
1he loowng tube shows the exceptons thrown by WRITEAPPEND().
fxccptiun Thruwn Whcn
VALUE_ERROR
Any ol the nput purumeters ure nu or nvud.
INVALID_ARGVAL
Lther:
amount < 1
amount > MAXBUFSIZE
fxampIc Pl/SQl Pruccdurcs
ln ths secton, you' see exumpe lL/SQL procedures thut use the vurous methods descrbed n
the prevous sectons. 1he exumpe procedures ure creuted when you run the lob_schema.sql
scrpt.
Rctricving a lOB lucatur
1he loowng get_clob_locator() procedure gets u LC ocutor lrom the clob_content
tube, get_clob_locator() perlorms the loowng tusks:
Accepts un IN OUT purumeter numed p_clob ol type CLOB, p_clob s set to u LC
ocutor nsde the procedure. ecuuse p_clob s IN OUT, the vuue s pussed out ol the
procedure.
Accepts un IN purumeter numed p_id ol type INTEGER, whch specles the id ol u row
to retreve lrom the clob_content tube.
Seects clob_column lrom the clob_content tube nto p_clob, ths stores the LC
ocutor ol clob_column n p_clob.
S04
Cruce Dutubuse ll SQL
CREATE PROCEDURE get_clob_locator(
p_clob IN OUT CLOB,
p_id IN INTEGER
) AS
BEGIN
-- get the LOB locator and store it in p_clob
SELECT clob_column
INTO p_clob
FROM clob_content
WHERE id = p_id;
END get_clob_locator;
/
1he loowng get_blob_locator() procedure does the sume thng us the prevous
procedure, except t gets the ocutor lor u BLOB lrom the blob_content tube:
CREATE PROCEDURE get_blob_locator(
p_blob IN OUT BLOB,
p_id IN INTEGER
) AS
BEGIN
-- get the LOB locator and store it in p_blob
SELECT blob_column
INTO p_blob
FROM blob_content
WHERE id = p_id;
END get_blob_locator;
/
1hese two procedures ure used n the code shown n the loowng sectons.
Rcading Data frum ClOBs and BlOBs
1he loowng read_clob_example() procedure reuds the dutu lrom u CLOB und dspuys the
dutu on the screen, read_clob_example() perlorms the loowng tusks:
Cus get_clob_locator() to get u ocutor und stores t n v_clob
Lses READ() to reud the contents ol v_clob nto u VARCHAR2 vurube numed
v_char_buffer
Dspuys the contents ol v_char_buffer on the screen
CREATE PROCEDURE read_clob_example(
p_id IN INTEGER
) AS
v_clob CLOB;
v_offset INTEGER := 1;
v_amount INTEGER := 50;
v_char_buffer VARCHAR2(50);
BEGIN
-- get the LOB locator and store it in v_clob
get_clob_locator(v_clob, p_id);
Chupter l4: Lurge Cbects

-- read the contents of v_clob into v_char_buffer, starting at


-- the v_offset position and read a total of v_amount characters
DBMS_LOB.READ(v_clob, v_amount, v_offset, v_char_buffer);
-- display the contents of v_char_buffer
DBMS_OUTPUT.PUT_LINE('v_char_buffer = ' || v_char_buffer);
DBMS_OUTPUT.PUT_LINE('v_amount = ' || v_amount);
END read_clob_example;
/
1he loowng exumpe turns the server output on und cus read_clob_example():
SET SERVEROUTPUT ON
CALL read_clob_example(1);
v_char_buffer = Creeps in this petty pace
v_amount = 25
1he loowng read_blob_example() procedure reuds the dutu lrom u BLOB, read_
blob_example() perlorms the loowng tusks:
Cus get_blob_locator()to get the ocutor und stores t n v_blob
Cus READ() to reud the contents ol v_blob nto u RAW vurube numed v_binary_
buffer
Dspuys the contents ol v_binary_buffer on the screen
CREATE PROCEDURE read_blob_example(
p_id IN INTEGER
) AS
v_blob BLOB;
v_offset INTEGER := 1;
v_amount INTEGER := 25;
v_binary_buffer RAW(25);
BEGIN
-- get the LOB locator and store it in v_blob
get_blob_locator(v_blob, p_id);
-- read the contents of v_blob into v_binary_buffer, starting at
-- the v_offset position and read a total of v_amount bytes
DBMS_LOB.READ(v_blob, v_amount, v_offset, v_binary_buffer);
-- display the contents of v_binary_buffer
DBMS_OUTPUT.PUT_LINE('v_binary_buffer = ' || v_binary_buffer);
DBMS_OUTPUT.PUT_LINE('v_amount = ' || v_amount);
END read_blob_example;
/
1he loowng exumpe cus read_blob_example():
CALL read_blob_example(1);
v_binary_buffer = 100111010101011111
v_amount = 9
S06
Cruce Dutubuse ll SQL
Writing tu a ClOB
1he loowng write_example() procedure wrtes u strng n v_char_buffer to v_clob
usng WRITE(), notce thut the SELECT stutement n the procedure uses the FOR UPDATE
cuuse, whch s used becuuse the CLOB s wrtten to usng WRITE():
CREATE PROCEDURE write_example(
p_id IN INTEGER
) AS
v_clob CLOB;
v_offset INTEGER := 7;
v_amount INTEGER := 6;
v_char_buffer VARCHAR2(10) := 'pretty';
BEGIN
-- get the LOB locator into v_clob for update (for update
-- because the LOB is written to using WRITE() later)
SELECT clob_column
INTO v_clob
FROM clob_content
WHERE id = p_id
FOR UPDATE;
-- read and display the contents of the CLOB
read_clob_example(p_id);
-- write the characters in v_char_buffer to v_clob, starting
-- at the v_offset position and write a total of v_amount characters
DBMS_LOB.WRITE(v_clob, v_amount, v_offset, v_char_buffer);
-- read and display the contents of the CLOB
-- and then rollback the write
read_clob_example(p_id);
ROLLBACK;
END write_example;
/
1he loowng exumpe cus write_example():
CALL write_example(1);
v_char_buffer = Creeps in this petty pace
v_amount = 25
v_char_buffer = Creepsprettyis petty pace
v_amount = 25
Appcnding Data tu a ClOB
1he loowng append_example() procedure uses APPEND() to copy the dutu lrom v_src_
clob to the end ol v_dest_clob:
CREATE PROCEDURE append_example AS
v_src_clob CLOB;
v_dest_clob CLOB;
BEGIN
-- get the LOB locator for the CLOB in row #2 of
Chupter l4: Lurge Cbects
S07
-- the clob_content table into v_src_clob
get_clob_locator(v_src_clob, 2);
-- get the LOB locator for the CLOB in row #1 of
-- the clob_content table into v_dest_clob for update
-- (for update because the CLOB will be added to using
-- APPEND() later)
SELECT clob_column
INTO v_dest_clob
FROM clob_content
WHERE id = 1
FOR UPDATE;
-- read and display the contents of CLOB #1
read_clob_example(1);
-- use APPEND() to copy the contents of v_src_clob to v_dest_clob
DBMS_LOB.APPEND(v_dest_clob, v_src_clob);
-- read and display the contents of CLOB #1
-- and then rollback the change
read_clob_example(1);
ROLLBACK;
END append_example;
/
1he loowng exumpe cus append_example():
CALL append_example();
v_char_buffer = Creeps in this petty pace
v_amount = 25
v_char_buffer = Creeps in this petty pace from day to day
v_amount = 41
Cumparing thc Data in Twu ClOBs
1he loowng compare_example() procedure compures the dutu n v_clob1 und v_clob2
usng COMPARE():
CREATE PROCEDURE compare_example AS
v_clob1 CLOB;
v_clob2 CLOB;
v_return INTEGER;
BEGIN
-- get the LOB locators
get_clob_locator(v_clob1, 1);
get_clob_locator(v_clob2, 2);
-- compare v_clob1 with v_clob2 (COMPARE() returns 1
-- because the contents of v_clob1 and v_clob2 are different)
DBMS_OUTPUT.PUT_LINE('Comparing v_clob1 with v_clob2');
v_return := DBMS_LOB.COMPARE(v_clob1, v_clob2);
DBMS_OUTPUT.PUT_LINE('v_return = ' || v_return);
S08
Cruce Dutubuse ll SQL
-- compare v_clob1 with v_clob1 (COMPARE() returns 0
-- because the contents are the same)
DBMS_OUTPUT.PUT_LINE('Comparing v_clob1 with v_clob1');
v_return := DBMS_LOB.COMPARE(v_clob1, v_clob1);
DBMS_OUTPUT.PUT_LINE('v_return = ' || v_return);
END compare_example;
/
1he loowng exumpe cus compare_example():
CALL compare_example();
Comparing v_clob1 with v_clob2
v_return = 1
Comparing v_clob1 with v_clob1
v_return = 0
Notce thut v_return s l when compurng v_clob1 wth v_clob2, whch ndcutes the
LC dutu s dllerent, v_return s 0 when compurng v_clob1 wth v_clob1, whch ndcutes
the LC dutu s the sume.
Cupying Data frum Onc ClOB tu Anuthcr
1he loowng copy_example() procedure copes some churucters lrom v_src_clob to
v_dest_clob usng COPY():
CREATE PROCEDURE copy_example AS
v_src_clob CLOB;
v_dest_clob CLOB;
v_src_offset INTEGER := 1;
v_dest_offset INTEGER := 7;
v_amount INTEGER := 5;
BEGIN
-- get the LOB locator for the CLOB in row #2 of
-- the clob_content table into v_dest_clob
get_clob_locator(v_src_clob, 2);
-- get the LOB locator for the CLOB in row #1 of
-- the clob_content table into v_dest_clob for update
-- (for update because the CLOB will be added to using
-- COPY() later)
SELECT clob_column
INTO v_dest_clob
FROM clob_content
WHERE id = 1
FOR UPDATE;
-- read and display the contents of CLOB #1
read_clob_example(1);
-- copy characters to v_dest_clob from v_src_clob using COPY(),
-- starting at the offsets specified by v_dest_offset and
-- v_src_offset for a total of v_amount characters
Chupter l4: Lurge Cbects
S09
DBMS_LOB.COPY(
v_dest_clob, v_src_clob,
v_amount, v_dest_offset, v_src_offset
);
-- read and display the contents of CLOB #1
-- and then rollback the change
read_clob_example(1);
ROLLBACK;
END copy_example;
/
1he loowng exumpe cus copy_example():
CALL copy_example();
v_char_buffer = Creeps in this petty pace
v_amount = 25
v_char_buffer = Creeps fromhis petty pace
v_amount = 25
Using Tcmpurary ClOBs
1he loowng temporary_lob_example() procedure ustrutes the use ol u temporury CLOB:
CREATE PROCEDURE temporary_lob_example AS
v_clob CLOB;
v_amount INTEGER;
v_offset INTEGER := 1;
v_char_buffer VARCHAR2(17) := 'Juliet is the sun';
BEGIN
-- use CREATETEMPORARY() to create a temporary CLOB named v_clob
DBMS_LOB.CREATETEMPORARY(v_clob, TRUE);
-- use WRITE() to write the contents of v_char_buffer to v_clob
v_amount := LENGTH(v_char_buffer);
DBMS_LOB.WRITE(v_clob, v_amount, v_offset, v_char_buffer);
-- use ISTEMPORARY() to check if v_clob is temporary
IF (DBMS_LOB.ISTEMPORARY(v_clob) = 1) THEN
DBMS_OUTPUT.PUT_LINE('v_clob is temporary');
END IF;
-- use READ() to read the contents of v_clob into v_char_buffer
DBMS_LOB.READ(
v_clob, v_amount, v_offset, v_char_buffer
);
DBMS_OUTPUT.PUT_LINE('v_char_buffer = ' || v_char_buffer);
-- use FREETEMPORARY() to free v_clob
DBMS_LOB.FREETEMPORARY(v_clob);
END temporary_lob_example;
/
S10
Cruce Dutubuse ll SQL
1he loowng exumpe cus temporary_lob_example():
CALL temporary_lob_example();
v_clob is temporary
v_char_buffer = Juliet is the sun
frasing Data frum a ClOB
1he loowng erase_example() procedure eruses purt ol u CLOB usng ERASE():
CREATE PROCEDURE erase_example IS
v_clob CLOB;
v_offset INTEGER := 2;
v_amount INTEGER := 5;
BEGIN
-- get the LOB locator for the CLOB in row #1 of
-- the clob_content table into v_dest_clob for update
-- (for update because the CLOB will be erased using
-- ERASE() later)
SELECT clob_column
INTO v_clob
FROM clob_content
WHERE id = 1
FOR UPDATE;
-- read and display the contents of CLOB #1
read_clob_example(1);
-- use ERASE() to erase a total of v_amount characters
-- from v_clob, starting at v_offset
DBMS_LOB.ERASE(v_clob, v_amount, v_offset);
-- read and display the contents of CLOB #1
-- and then rollback the change
read_clob_example(1);
ROLLBACK;
END erase_example;
/
1he loowng exumpe cus erase_example():
CALL erase_example();
v_char_buffer = Creeps in this petty pace
v_amount = 25
v_char_buffer = C in this petty pace
v_amount = 25
Scarching thc Data in a ClOB
1he loowng instr_example() procedure uses INSTR() to seurch the churucter dutu stored
n u CLOB:
Chupter l4: Lurge Cbects

CREATE PROCEDURE instr_example AS


v_clob CLOB;
v_char_buffer VARCHAR2(50) := 'It is the east and Juliet is the sun';
v_pattern VARCHAR2(5);
v_offset INTEGER := 1;
v_amount INTEGER;
v_occurrence INTEGER;
v_return INTEGER;
BEGIN
-- use CREATETEMPORARY() to create a temporary CLOB named v_clob
DBMS_LOB.CREATETEMPORARY(v_clob, TRUE);
-- use WRITE() to write the contents of v_char_buffer to v_clob
v_amount := LENGTH(v_char_buffer);
DBMS_LOB.WRITE(v_clob, v_amount, v_offset, v_char_buffer);
-- use READ() to read the contents of v_clob into v_char_buffer
DBMS_LOB.READ(v_clob, v_amount, v_offset, v_char_buffer);
DBMS_OUTPUT.PUT_LINE('v_char_buffer = ' || v_char_buffer);
-- use INSTR() to search v_clob for the second occurrence of is,
-- and INSTR() returns 27
DBMS_OUTPUT.PUT_LINE('Searching for second ''is''');
v_pattern := 'is';
v_occurrence := 2;
v_return := DBMS_LOB.INSTR(v_clob, v_pattern, v_offset, v_occurrence);
DBMS_OUTPUT.PUT_LINE('v_return = ' || v_return);
-- use INSTR() to search v_clob for the first occurrence of Moon,
-- and INSTR() returns 0 because Moon doesn't appear in v_clob
DBMS_OUTPUT.PUT_LINE('Searching for ''Moon''');
v_pattern := 'Moon';
v_occurrence := 1;
v_return := DBMS_LOB.INSTR(v_clob, v_pattern, v_offset, v_occurrence);
DBMS_OUTPUT.PUT_LINE('v_return = ' || v_return);
-- use FREETEMPORARY() to free v_clob
DBMS_LOB.FREETEMPORARY(v_clob);
END instr_example;
/
1he loowng exumpe cus instr_example():
CALL instr_example();
v_char_buffer = It is the east and Juliet is the sun
Searching for second 'is'
v_return = 27
Searching for 'Moon'
v_return = 0
S12
Cruce Dutubuse ll SQL
Cupying Data frum a fiIc intu a ClOB and a BlOB
1he loowng copy_file_data_to_clob() procedure shows how to reud text lrom u le und
store t n u CLOB:
CREATE PROCEDURE copy_file_data_to_clob(
p_clob_id INTEGER,
p_directory VARCHAR2,
p_file_name VARCHAR2
) AS
v_file UTL_FILE.FILE_TYPE;
v_chars_read INTEGER;
v_dest_clob CLOB;
v_amount INTEGER := 32767;
v_char_buffer VARCHAR2(32767);
BEGIN
-- insert an empty CLOB
INSERT INTO clob_content(
id, clob_column
) VALUES (
p_clob_id, EMPTY_CLOB()
);
-- get the LOB locator of the CLOB
SELECT clob_column
INTO v_dest_clob
FROM clob_content
WHERE id = p_clob_id
FOR UPDATE;
-- open the file for reading of text (up to v_amount characters per line)
v_file := UTL_FILE.FOPEN(p_directory, p_file_name, 'r', v_amount);
-- copy the data from the file into v_dest_clob one line at a time
LOOP
BEGIN
-- read a line from the file into v_char_buffer;
-- GET_LINE() does not copy the newline character into
-- v_char_buffer
UTL_FILE.GET_LINE(v_file, v_char_buffer);
v_chars_read := LENGTH(v_char_buffer);
-- append the line to v_dest_clob
DBMS_LOB.WRITEAPPEND(v_dest_clob, v_chars_read, v_char_buffer);
-- append a newline to v_dest_clob because v_char_buffer;
-- the ASCII value for newline is 10, so CHR(10) returns newline
DBMS_LOB.WRITEAPPEND(v_dest_clob, 1, CHR(10));
EXCEPTION
-- when there is no more data in the file then exit
Chupter l4: Lurge Cbects

WHEN NO_DATA_FOUND THEN


EXIT;
END;
END LOOP;
-- close the file
UTL_FILE.FCLOSE(v_file);
DBMS_OUTPUT.PUT_LINE('Copy successfully completed.');
END copy_file_data_to_clob;
/
1here ure u number ol thngs to note ubout ths procedure:
UTL_FILE s u puckuge ncuded wth the dutubuse und contuns methods und types thut
enube you to reud und wrte les. lor exumpe, UTL_FILE.FILE_TYPE s un obect
type used to represent u le.
1he v_amount vurube s set to 32767, whch s the muxmum number ol churucters
thut cun be reud lrom u le durng euch reud operuton.
1he v_char_buffer vurube s used to store the resuts reud lrom the le belore they
ure uppended to v_dest_clob. 1he muxmum ength ol v_char_buffer s set to
32767, ths ength s urge enough to store the muxmum number ol churucters reud lrom
the le durng euch reud operuton.
UTL_FILE.FOPEN(directory, file_name, open_mode, amount) opens u le,
open_mode cun be set to one ol the loowng modes:
r to reud text
w to wrte text
a to uppend text
rb to reud bytes
wb to wrte bytes
ab to uppend bytes
UTL_FILE.GET_LINE(v_file, v_char_buffer) gets u ne ol text lrom v_file
nto v_char_buffer. GET_LINE() does not udd the newne to v_char_buffer,
becuuse l wunt the newne, l udd t usng DBMS_LOB.WRITEAPPEND(v_dest_clob,
1, CHR(10)).
1he loowng exumpe cus copy_file_data_to_clob() to copy the contents ol the le
textContent.txt to u new CLOB wth un id ol 3:
CALL copy_file_data_to_clob(3, 'SAMPLE_FILES_DIR', 'textContent.txt');
Copy successfully completed.

Cruce Dutubuse ll SQL
1he loowng copy_file_data_to_blob() procedure shows how to reud bnury dutu
lrom u le und store t n u BLOB, notce thut u RAW urruy s used to store the bnury dutu reud
lrom the le:
CREATE PROCEDURE copy_file_data_to_blob(
p_blob_id INTEGER,
p_directory VARCHAR2,
p_file_name VARCHAR2
) AS
v_file UTL_FILE.FILE_TYPE;
v_bytes_read INTEGER;
v_dest_blob BLOB;
v_amount INTEGER := 32767;
v_binary_buffer RAW(32767);
BEGIN
-- insert an empty BLOB
INSERT INTO blob_content(
id, blob_column
) VALUES (
p_blob_id, EMPTY_BLOB()
);
-- get the LOB locator of the BLOB
SELECT blob_column
INTO v_dest_blob
FROM blob_content
WHERE id = p_blob_id
FOR UPDATE;
-- open the file for reading of bytes (up to v_amount bytes at a time)
v_file := UTL_FILE.FOPEN(p_directory, p_file_name, 'rb', v_amount);
-- copy the data from the file into v_dest_blob
LOOP
BEGIN
-- read binary data from the file into v_binary_buffer
UTL_FILE.GET_RAW(v_file, v_binary_buffer, v_amount);
v_bytes_read := LENGTH(v_binary_buffer);
-- append v_binary_buffer to v_dest_blob
DBMS_LOB.WRITEAPPEND(v_dest_blob, v_bytes_read/2,
v_binary_buffer);
EXCEPTION
-- when there is no more data in the file then exit
WHEN NO_DATA_FOUND THEN
EXIT;
END;
END LOOP;
-- close the file
UTL_FILE.FCLOSE(v_file);
Chupter l4: Lurge Cbects
S1S
DBMS_OUTPUT.PUT_LINE('Copy successfully completed.');
END copy_file_data_to_blob;
/
1he loowng exumpe cus copy_file_data_to_blob() to copy the contents ol the le
binaryContent.doc to u new BLOB wth un id ol 3:
CALL copy_file_data_to_blob(3, 'SAMPLE_FILES_DIR', 'binaryContent.doc');
Copy successfully completed.
Cl course, copy_file_data_to_blob() cun be used to wrte uny bnury dutu contuned
n u le to u BLOB. 1he bnury dutu cun contun musc, vdeo, muges, executubes, und so on. Co
uheud und try ths usng your own les.
TlP
You can ao bu|-oad da|a n|o a C ung |hc Cracc S*oadcr
and Da|a ump u||c, cc |hc Cruce Dutubuse Lurge Cbects
Deveoper's Cude pubhcd b, Cracc Corpora|on |or dc|a.
Cupying Data frum a ClOB and a BlOB tu a fiIc
1he loowng copy_clob_data_to_file() procedure shows how to reud text lrom u CLOB
und suve t to u le:
CREATE PROCEDURE copy_clob_data_to_file(
p_clob_id INTEGER,
p_directory VARCHAR2,
p_file_name VARCHAR2
) AS
v_src_clob CLOB;
v_file UTL_FILE.FILE_TYPE;
v_offset INTEGER := 1;
v_amount INTEGER := 32767;
v_char_buffer VARCHAR2(32767);
BEGIN
-- get the LOB locator of the CLOB
SELECT clob_column
INTO v_src_clob
FROM clob_content
WHERE id = p_clob_id;
-- open the file for writing of text (up to v_amount characters at a time)
v_file := UTL_FILE.FOPEN(p_directory, p_file_name, 'w', v_amount);
-- copy the data from v_src_clob to the file
LOOP
BEGIN
-- read characters from v_src_clob into v_char_buffer
DBMS_LOB.READ(v_src_clob, v_amount, v_offset, v_char_buffer);
-- copy the characters from v_char_buffer to the file
UTL_FILE.PUT(v_file, v_char_buffer);

Cruce Dutubuse ll SQL
-- add v_amount to v_offset
v_offset := v_offset + v_amount;
EXCEPTION
-- when there is no more data in the file then exit
WHEN NO_DATA_FOUND THEN
EXIT;
END;
END LOOP;
-- flush any remaining data to the file
UTL_FILE.FFLUSH(v_file);
-- close the file
UTL_FILE.FCLOSE(v_file);
DBMS_OUTPUT.PUT_LINE('Copy successfully completed.');
END copy_clob_data_to_file;
/
1he loowng exumpe cus copy_clob_data_to_file() to copy the contents ol CLOB
r3 to u new le numed textContent2.txt:
CALL copy_clob_data_to_file(3, 'SAMPLE_FILES_DIR', 'textContent2.txt');
Copy successfully completed.
ll you ook n the C:\sample_files drectory, you w lnd the new textContent2.txt
le. 1hs le contuns dentcu text to textContent.txt.
1he loowng copy_blob_data_to_file() procedure shows how to reud bnury dutu
lrom u BLOB und suve t to u le:
CREATE PROCEDURE copy_blob_data_to_file(
p_blob_id INTEGER,
p_directory VARCHAR2,
p_file_name VARCHAR2
) AS
v_src_blob BLOB;
v_file UTL_FILE.FILE_TYPE;
v_offset INTEGER := 1;
v_amount INTEGER := 32767;
v_binary_buffer RAW(32767);
BEGIN
-- get the LOB locator of the BLOB
SELECT blob_column
INTO v_src_blob
FROM blob_content
WHERE id = p_blob_id;
-- open the file for writing of bytes (up to v_amount bytes at a time)
v_file := UTL_FILE.FOPEN(p_directory, p_file_name, 'wb', v_amount);
-- copy the data from v_src_blob to the file
Chupter l4: Lurge Cbects
S17
LOOP
BEGIN
-- read characters from v_src_blob into v_binary_buffer
DBMS_LOB.READ(v_src_blob, v_amount, v_offset, v_binary_buffer);
-- copy the binary data from v_binary_buffer to the file
UTL_FILE.PUT_RAW(v_file, v_binary_buffer);
-- add v_amount to v_offset
v_offset := v_offset + v_amount;
EXCEPTION
-- when there is no more data in the file then exit
WHEN NO_DATA_FOUND THEN
EXIT;
END;
END LOOP;
-- flush any remaining data to the file
UTL_FILE.FFLUSH(v_file);
-- close the file
UTL_FILE.FCLOSE(v_file);
DBMS_OUTPUT.PUT_LINE('Copy successfully completed.');
END copy_blob_data_to_file;
/
1he loowng exumpe cus copy_blob_data_to_file() to copy the contents ol BLOB
r3 to u new le numed binaryContent2.doc:
CALL copy_blob_data_to_file(3, 'SAMPLE_FILES_DIR', 'binaryContent2.doc');
Copy successfully completed.
ll you ook n the C:\sample_files drectory, you w lnd the new binaryContent2
.doc le. 1hs le contuns dentcu text to binaryContent.doc.
Cl course, copy_blob_data_to_file() cun be used to wrte uny bnury dutu contuned
n u BLOB to u le. 1he bnury dutu cun contun musc, vdeo, muges, executubes, und so on.
Cupying Data frum a Bfllf tu a ClOB and a BlOB
1he loowng copy_bfile_data_to_clob() procedure shows how to reud text lrom u
BFILE und suve t to u CLOB:
CREATE PROCEDURE copy_bfile_data_to_clob(
p_bfile_id INTEGER,
p_clob_id INTEGER
) AS
v_src_bfile BFILE;
v_directory VARCHAR2(200);
v_filename VARCHAR2(200);
v_length INTEGER;
v_dest_clob CLOB;

Cruce Dutubuse ll SQL
v_amount INTEGER := DBMS_LOB.LOBMAXSIZE;
v_dest_offset INTEGER := 1;
v_src_offset INTEGER := 1;
v_src_csid INTEGER := DBMS_LOB.DEFAULT_CSID;
v_lang_context INTEGER := DBMS_LOB.DEFAULT_LANG_CTX;
v_warning INTEGER;
BEGIN
-- get the locator of the BFILE
SELECT bfile_column
INTO v_src_bfile
FROM bfile_content
WHERE id = p_bfile_id;
-- use FILEEXISTS() to check if the file exists
-- (FILEEXISTS() returns 1 if the file exists)
IF (DBMS_LOB.FILEEXISTS(v_src_bfile) = 1) THEN
-- use OPEN() to open the file
DBMS_LOB.OPEN(v_src_bfile);
-- use FILEGETNAME() to get the name of the file and the directory
DBMS_LOB.FILEGETNAME(v_src_bfile, v_directory, v_filename);
DBMS_OUTPUT.PUT_LINE('Directory = ' || v_directory);
DBMS_OUTPUT.PUT_LINE('Filename = ' || v_filename);
-- insert an empty CLOB
INSERT INTO clob_content(
id, clob_column
) VALUES (
p_clob_id, EMPTY_CLOB()
);
-- get the LOB locator of the CLOB (for update)
SELECT clob_column
INTO v_dest_clob
FROM clob_content
WHERE id = p_clob_id
FOR UPDATE;
-- use LOADCLOBFROMFILE() to get up to v_amount characters
-- from v_src_bfile and store them in v_dest_clob, starting
-- at offset 1 in v_src_bfile and v_dest_clob
DBMS_LOB.LOADCLOBFROMFILE(
v_dest_clob, v_src_bfile,
v_amount, v_dest_offset, v_src_offset,
v_src_csid, v_lang_context, v_warning
);
-- check v_warning for an inconvertible character
IF (v_warning = DBMS_LOB.WARN_INCONVERTIBLE_CHAR) THEN
DBMS_OUTPUT.PUT_LINE('Warning! Inconvertible character.');
END IF;
Chupter l4: Lurge Cbects

-- use CLOSE() to close v_src_bfile


DBMS_LOB.CLOSE(v_src_bfile);
DBMS_OUTPUT.PUT_LINE('Copy successfully completed.');
ELSE
DBMS_OUTPUT.PUT_LINE('File does not exist');
END IF;
END copy_bfile_data_to_clob;
/
1he loowng exumpe cus copy_bfile_data_to_clob() to copy the contents ol
BFILE rl to u new CLOB wth un id ol 4:
CALL copy_bfile_data_to_clob(1, 4);
Copy successfully completed.
1he next exumpe cus copy_clob_data_to_file() to copy the contents ol CLOB r4 to
u new le numed textContent3.txt:
CALL copy_clob_data_to_file(4, 'SAMPLE_FILES_DIR', 'textContent3.txt');
Copy successfully completed.
ll you ook n the C:\sample_files drectory, you w lnd the new textContent3.txt
le. 1hs le contuns dentcu text to textContent.txt.
1he loowng copy_bfile_data_to_blob() procedure shows how to reud bnury dutu
lrom u BFILE und suve t to u BLOB:
CREATE PROCEDURE copy_bfile_data_to_blob(
p_bfile_id INTEGER,
p_blob_id INTEGER
) AS
v_src_bfile BFILE;
v_directory VARCHAR2(200);
v_filename VARCHAR2(200);
v_length INTEGER;
v_dest_blob BLOB;
v_amount INTEGER := DBMS_LOB.LOBMAXSIZE;
v_dest_offset INTEGER := 1;
v_src_offset INTEGER := 1;
BEGIN
-- get the locator of the BFILE
SELECT bfile_column
INTO v_src_bfile
FROM bfile_content
WHERE id = p_bfile_id;
-- use FILEEXISTS() to check if the file exists
-- (FILEEXISTS() returns 1 if the file exists)
IF (DBMS_LOB.FILEEXISTS(v_src_bfile) = 1) THEN
-- use OPEN() to open the file
DBMS_LOB.OPEN(v_src_bfile);
-- use FILEGETNAME() to get the name of the file and

Cruce Dutubuse ll SQL
-- the directory
DBMS_LOB.FILEGETNAME(v_src_bfile, v_directory, v_filename);
DBMS_OUTPUT.PUT_LINE('Directory = ' || v_directory);
DBMS_OUTPUT.PUT_LINE('Filename = ' || v_filename);
-- insert an empty BLOB
INSERT INTO blob_content(
id, blob_column
) VALUES (
p_blob_id, EMPTY_BLOB()
);
-- get the LOB locator of the BLOB (for update)
SELECT blob_column
INTO v_dest_blob
FROM blob_content
WHERE id = p_blob_id
FOR UPDATE;
-- use LOADBLOBFROMFILE() to get up to v_amount bytes
-- from v_src_bfile and store them in v_dest_blob, starting
-- at offset 1 in v_src_bfile and v_dest_blob
DBMS_LOB.LOADBLOBFROMFILE(
v_dest_blob, v_src_bfile,
v_amount, v_dest_offset, v_src_offset
);
-- use CLOSE() to close v_src_bfile
DBMS_LOB.CLOSE(v_src_bfile);
DBMS_OUTPUT.PUT_LINE('Copy successfully completed.');
ELSE
DBMS_OUTPUT.PUT_LINE('File does not exist');
END IF;
END copy_bfile_data_to_blob;
/
1he loowng exumpe cus copy_bfile_data_to_blob() to copy the contents ol
BFILE r2 to u new BLOB wth un id ol 4:
CALL copy_bfile_data_to_blob(2, 4);
Copy successfully completed.
1he next exumpe cus copy_blob_data_to_file() to copy the contents ol BLOB r4 to
u new le numed binaryContent3.doc:
CALL copy_blob_data_to_file(4, 'SAMPLE_FILES_DIR', 'binaryContent3.doc');
Copy successfully completed.
ll you ook n the C:\sample_files drectory, you w lnd the new binaryContent3
.doc le. 1hs le contuns dentcu text to binaryContent.doc.
1hs s the end ol the coveruge on urge obects. ln the next secton, you' eurn ubout the
LONG und LONG RAW types.
Chupter l4: Lurge Cbects
S21
lONG and lONG RAW Typcs
l mentoned ut the sturt ol ths chupter thut LCs ure the prelerred storuge type lor urge bocks ol
dutu, but you muy encounter dutubuses thut st use the loowng types:
LONG Lsed to store up to 2 ggubytes ol churucter dutu
LONG RAW Lsed to store up to 2 ggubytes ol bnury dutu
RAW Lsed to store up to 4 kobytes ol bnury dutu
ln ths secton, you' eurn how to use LONG und LONG RAW types. RAW s used n the sume
wuy us u LONG RAW, so l've omtted coveruge ol RAW.
Thc fxampIc TabIcs
ln ths secton, you' see the use ol the loowng two tubes:
long_content Contuns u LONG coumn numed long_column
long_raw_content Contuns u LONG RAW coumn numed long_raw_column
1hese two tubes ure creuted by the lob_schema.sql scrpt usng the loowng stutements:
CREATE TABLE long_content (
id INTEGER PRIMARY KEY,
long_column LONG NOT NULL
);
CREATE TABLE long_raw_content (
id INTEGER PRIMARY KEY,
long_raw_column LONG RAW NOT NULL
);
Adding Data tu lONG and lONG RAW CuIumns
1he loowng INSERT stutements udd rows to the long_content tube:
INSERT INTO long_content (
id, long_column
) VALUES (
1, 'Creeps in this petty pace'
);
INSERT INTO long_content (
id, long_column
) VALUES (
2, ' from day to day'
);
1he loowng INSERT stutements udd rows to the long_raw_content tube (the lrst
INSERT contuns u bnury number, the second u hexudecmu number):
INSERT INTO long_raw_content (
id, long_raw_column
S22
Cruce Dutubuse llg SQL
) VALUES (
1, '100111010101011111'
);
INSERT INTO long_raw_content (
id, long_raw_column
) VALUES (
2, 'A0FFB71CF90DE'
);
ln the next secton, you' see how to convert LONG und LONG RAW coumns to LCs.
Cunvcrting lONG and lONG RAW CuIumns tu lOBs
You cun convert u LONG to u CLOB usng the TO_LOB() luncton. lor exumpe, the loowng
stutement converts long_column to u CLOB usng TO_LOB() und stores the resuts n the
clob_content tube:
INSERT INTO clob_content
SELECT 10 + id, TO_LOB(long_column)
FROM long_content;
2 rows created.
You cun convert u LONG RAW to u BLOB usng the TO_LOB() luncton. lor exumpe, the
loowng stutement converts long_raw_column to u BLOB usng TO_LOB() und stores
the resuts n the blob_content tube:
INSERT INTO blob_content
SELECT 10 + id, TO_LOB(long_raw_column)
FROM long_raw_content;
2 rows created.
You cun uso use the ALTER TABLE stutement to convert LONG und LONG RAW coumns
drecty. lor exumpe, the loowng stutement converts long_column to u CLOB:
ALTER TABLE long_content MODIFY (long_column CLOB);
1he next exumpe converts long_raw_column to u BLOB:
ALTER TABLE long_raw_content MODIFY (long_raw_column BLOB);
CAUTlON
You houd no| mod|, |abc |ha| arc currcn|, ucd n a produc|on
appca|on.
Cnce u LONG or LONG RAW coumn s converted to u LC, you cun use the rch lL/SQL
methods descrbed eurer to uccess the LC.
Chupter l4: Lurge Cbects
S23
OracIc Databasc 10 fnhanccmcnts
tu largc Objccts
ln ths secton, you' eurn ubout the loowng enhuncements mude to urge obects n Cruce
Dutubuse l0:
lmpct converson between CLOB und NCLOB obects
Lse ol the :new uttrbute when usng LCs n u trgger
l've provded un SQL*lus scrpt numed lob_schema2.sql n the SQL drectory. 1hs scrpt
cun be run usng Cruce Dutubuse l0 und hgher. 1he scrpt creutes u user numed lob_user2
wth u pussword ol lob_password und creutes the tubes und lL/SQL code used n ths secton.
Alter the scrpt competes, you w be ogged n us lob_user2.
lmpIicit Cunvcrsiun Bctwccn ClOB and NClOB Objccts
ln toduy's gobu busness envronment, you mght huve to deu wth conversons between
Lncode und u nutonu unguuge churucter set. Lncode s u unversu churucter set thut enubes
you to store text thut cun be converted nto uny unguuge, t does ths by provdng u unque code
lor every churucter, regurdess ol the unguuge. A nutonu churucter set stores text n u speclc
unguuge.
ln versons ol the dutubuse beow Cruce Dutubuse l0, you huve to expcty convert between
Lncode text und the nutonu churucter set text usng the TO_CLOB() und TO_NCLOB() lunctons.
TO_CLOB() uows you to convert text stored n u VARCHAR2, NVARCHAR2, or NCLOB to u CLOB.
Smury, TO_NCLOB() uows you to convert text stored n u VARCHAR2, NVARCHAR2, or CLOB to
un NCLOB.
Cruce Dutubuse l0 und hgher mpcty converts Lncode text und nutonu churucter set
text n CLOB und NCLOB obects, whch suves you lrom usng TO_CLOB() und TO_NCLOB().
You cun use ths mpct converson lor IN und OUT vurubes n queres und DML stutements us
we us lor lL/SQL method purumeters und vurube ussgnments.
Let's tuke u ook ut un exumpe. 1he loowng stutement creutes u tube numed nclob_
content thut contuns un NCLOB coumn numed nclob_column:
CREATE TABLE nclob_content (
id INTEGER PRIMARY KEY,
nclob_column NCLOB
);
1he loowng nclob_example() procedure shows the mpct converson ol u CLOB to un
NCLOB, und vce versu:
CREATE PROCEDURE nclob_example
AS
v_clob CLOB := 'It is the east and Juliet is the sun';
v_nclob NCLOB;
BEGIN
S24
Cruce Dutubuse ll SQL
-- insert v_clob into nclob_column; this implicitly
-- converts the CLOB v_clob to an NCLOB, storing
-- the contents of v_clob in the nclob_content table
INSERT INTO nclob_content (
id, nclob_column
) VALUES (
1, v_clob
);
-- select nclob_column into v_clob; this implicitly
-- converts the NCLOB stored in nclob_column to a
-- CLOB, retrieving the contents of nclob_column
-- into v_clob
SELECT nclob_column
INTO v_clob
FROM nclob_content
WHERE id = 1;
-- display the contents of v_clob
DBMS_OUTPUT.PUT_LINE('v_clob = ' || v_clob);
END nclob_example;
/
1he loowng exumpe turns the server output on und cus nclob_example():
SET SERVEROUTPUT ON
CALL nclob_example();
v_clob = It is the east and Juliet is the sun
Usc uf thc :ncw Attributc Whcn Using lOBs in a Triggcr
ln Cruce Dutubuse l0 und hgher, you cun use the :new uttrbute when relerencng LCs n u
BEFORE UPDATE or BEFORE INSERT row eve trgger. 1he loowng exumpe creutes u trgger
numed before_clob_content_update, the trgger lres when the clob_content tube s
upduted und dspuys the ength ol the new dutu n clob_column, notce thut :new s used to
uccess the new dutu n clob_column:
CREATE TRIGGER before_clob_content_update
BEFORE UPDATE
ON clob_content
FOR EACH ROW
BEGIN
DBMS_OUTPUT.PUT_LINE('clob_content changed');
DBMS_OUTPUT.PUT_LINE(
'Length = ' || DBMS_LOB.GETLENGTH(:new.clob_column)
);
END before_clob_content_update;
/
1he loowng exumpe updutes the clob_content tube, cuusng the trgger to be lred:
Chupter l4: Lurge Cbects
S2S
UPDATE clob_content
SET clob_column = 'Creeps in this petty pace'
WHERE id = 1;
clob_content changed
Length = 25
OracIc Databasc 11 fnhanccmcnts
tu largc Objccts
ln ths secton, you' eurn ubout the loowng enhuncements mude to urge obects n Cruce
Dutubuse ll:
Lncrypton ol BLOB, CLOB, und NCLOB dutu, whch prevents unuuthorzed vewng und
modlcuton ol the dutu
Compresson to squeeze BLOB, CLOB, und NCLOB dutu
De-dupcuton ol BLOB, CLOB, und NCLOB dutu to uutomutcuy detect und remove
repeuted dutu
fncrypting lOB Data
You cun dsguse your dutu usng encrypton so thut unuuthorzed users cunnot vew or modly
t. You shoud encrypt senstve dutu such us credt curd numbers, socu securty numbers, und
so on.
elore you cun encrypt dutu, ether you or u dutubuse udmnstrutor needs to set up u wuet
to store securty detus. 1he dutu n u wuet ncudes u prvute key lor encryptng und decryptng
dutu. ln ths secton, you' see how to creute u wuet, encrypt LC dutu, und encrypt reguur
coumn dutu.
Crcating a WaIIct
1o creute u wuet, you must lrst creute u drectory cued wallet n the drectory $ORACLE_
BASE\admin\$ORACLE_SID, where ORACLE_BASE s the buse drectory where the Cruce
dutubuse soltwure s nstued, und ORACLE_SID s the system dentler lor the dutubuse n whch
the wuet s to be creuted. lor exumpe, on my computer runnng \ndows Xl und Cruce
Dutubuse ll, l creuted my wallet directory n C:\oracle_11g\admin\orcl.
Cnce the wuet drectory s creuted, you need to run SQL*lus, connect to the dutubuse usng
u prveged user uccount (lor exumpe, system), und run un ALTER SYSTEM commund to set
the pussword lor the wuet encrypton key, us shown here:
SQL> CONNECT system/manager
SQL> ALTER SYSTEM SET ENCRYPTION KEY IDENTIFIED BY "testpassword123";
System altered.
Cnce ths s done, u le cued ewallet.p12 uppeurs n the wallet drectory, und the
dutubuse uutomutcuy opens the wuet. 1he encrypton key pussword s stored n the wuet,
und s used to encrypt und decrypt dutu behnd the scenes.
S26
Cruce Dutubuse ll SQL
l've provded un SQL*lus scrpt numed lob_schema3.sql n the SQL drectory. 1hs scrpt
muy be run usng Cruce Dutubuse ll. 1he scrpt creutes u user numed lob_user3 wth u
pussword ol lob_password, und t uso creutes the tubes used uter n ths secton. Alter the
scrpt competes, you w be ogged n us lob_user3.
fncrypting lOB Data
You cun encrypt the dutu stored n u BLOB, CLOB, or NCLOB to prevent unuuthorzed uccess to
thut dutu, you cunnot encrypt u BFILE, becuuse the le tsel s stored outsde the dutubuse.
You cun use the loowng ugorthms to encrypt dutu:
3DfS168 1he 1rpe-DLS (Dutu Lncrypton Stundurd) ugorthm wth u key ength ol
l68 bts.
AfS128 1he Advunced Lncrypton Stundurd ugorthm wth u key ength ol l28 bts.
1he ALS ugorthms were deveoped to repuce the oder ugorthms bused on DLS.
AfS192 1he Advunced Lncrypton Stundurd ugorthm wth u key ength ol l92 bts.
AfS2S6 1he Advunced Lncrypton Stundurd ugorthm wth u key ength ol 256 bts.
1hs s the most secure encrypton ugorthm supported by the Cruce dutubuse.
1he loowng stutement creutes u tube wth u CLOB whose contents ure to be encrypted
usng the ALSl28 ugorthm, notce the use ol the ENCRYPT und SECUREFILE keywords, whch
ure requred when encryptng dutu:
CREATE TABLE clob_content (
id INTEGER PRIMARY KEY,
clob_column CLOB ENCRYPT USING 'AES128'
) LOB(clob_column) STORE AS SECUREFILE (
CACHE
);
As you cun see, the contents ol clob_column w be encrypted usng the ALSl28 ugorthm.
ll you omt the USING keyword und the ugorthm, then the deluut ALSl92 ugorthm s used.
1he CACHE keyword n the CREATE TABLE stutement ndcutes thut the dutubuse puces dutu
lrom the LC nto the buller cuche lor luster uccess. 1he optons you cun use lor buller cuchng
ure us loows:
CACHE READS Lse when the LC dutu w be lrequenty reud, but wrtten ony once
or occusonuy.
CACHE Lse when the LC dutu w be lrequenty reud und lrequenty wrtten.
NOCACHE Lse when the LC dutu w be reud once or occusonuy und wrtten once
or occusonuy. 1hs s the deluut opton.
1he loowng INSERT stutements udd two rows to the clob_content tube:
INSERT INTO clob_content (
id, clob_column
) VALUES (
1, TO_CLOB('Creeps in this petty pace')
Chupter l4: Lurge Cbects

);
INSERT INTO clob_content (
id, clob_column
) VALUES (
2, TO_CLOB(' from day to day')
);
1he dutu supped to clob_column n these stutements ure uutomutcuy encrypted behnd
the scenes by the dutubuse.
1he loowng query retreves the rows lrom the clob_content tube:
SELECT *
FROM clob_content;
ID
----------
CLOB_COLUMN
-------------------------
1
Creeps in this petty pace
2
from day to day
\hen the dutu s retreved, t s uutomutcuy decrypted by the dutubuse und then returned to
SQL*lus.
As ong us the wuet s open, you cun store und retreve encrypted dutu, when the wuet s
cosed, you cunnot. Let's see whut huppens when the wuet s cosed, the loowng stutements
connect us the system user und cose the wuet:
CONNECT system/manager
ALTER SYSTEM SET WALLET CLOSE;
ll you now uttempt to connect us lob_user3 und retreve clob_column lrom the clob_
content tube, you get the error ORA-28365: wallet is not open:
CONNECT lob_user3/lob_password
SELECT clob_column
FROM clob_content;
ORA-28365: wallet is not open
You cun st retreve und modly the contents ol unencrypted coumns, lor exumpe, the
loowng query retreves the id coumn lrom the clob_content tube:
SELECT id
FROM clob_content;
ID
----------
1
2
S28
Cruce Dutubuse llg SQL
1he loowng stutements connect us the system user und re-open the wuet:
CONNECT system/manager
ALTER SYSTEM SET WALLET OPEN IDENTIFIED BY "testpassword123";
Cnce ths s done, you cun retreve und modly the contents ol clob_column lrom the clob_
content tube.
fncrypting CuIumn Data
You cun uso encrypt reguur coumn dutu. 1hs leuture wus ntroduced n Cruce Dutubuse l0g
Reeuse 2. lor exumpe, the loowng stutement creutes u tube numed credit_cards wth un
encrypted coumn numed card_number:
CREATE TABLE credit_cards (
card_number NUMBER(16, 0) ENCRYPT,
first_name VARCHAR2(10),
last_name VARCHAR2(10),
expiration DATE
);
You cun use the sume ugorthms to encrypt u coumn us lor u LC: 3DLSl68, ALSl28,
ALSl92 (the deluut), und ALS256. ecuuse l ddn't specly un ugorthm ulter the ENCRYPT
keyword lor the card_number coumn, the deluut ALSl92 ugorthm s used.
1he loowng INSERT stutements udd two rows to the credit_cards tube:
INSERT INTO credit_cards (
card_number, first_name, last_name, expiration
) VALUES (
1234, 'Jason', 'Bond', '03-FEB-2008'
);
INSERT INTO credit_cards (
card_number, first_name, last_name, expiration
) VALUES (
5768, 'Steve', 'Edwards', '07-MAR-2009'
);
As ong us the wuet s open, you cun retreve und modly the contents ol the card_number
coumn. ll the wuet s cosed, you get the error ORA-28365: wallet is not open. You
suw exumpes thut ustrute these concepts n the prevous secton, so l won't repeut smur
exumpes here.
Accessng dutu n un encrypted coumn ntroduces uddtonu overheud. 1he overheud lor
encryptng or decryptng u coumn s estmuted by Cruce Corporuton to be ubout 5 percent, ths
meuns u SELECT or un INSERT tukes ubout 5 percent more tme to compete. 1he totu overheud
depends on the number ol encrypted coumns und ther lrequency ol uccess, therelore, you
shoud ony encrypt coumns thut contun senstve dutu.
NOTf
| ,ou arc n|crc|cd n carnng morc abou| vac| and da|abac
ccur|, gcncra,, ,ou houd rcad |hc Advunced Securty
Admnstrutor's Cude pubhcd b, Cracc Corpora|on.
Chupter l4: Lurge Cbects
S29
Cumprcssing lOB Data
You cun compress the dutu stored n u BLOB, CLOB, or NCLOB to reduce storuge spuce. lor
exumpe, the loowng stutement creutes u tube wth u CLOB whose contents ure to be compressed,
notce the use ol the COMPRESS keyword:
CREATE TABLE clob_content3 (
id INTEGER PRIMARY KEY,
clob_column CLOB
) LOB(clob_column) STORE AS SECUREFILE (
COMPRESS
CACHE
);
NOTf
vcn |hough |hc |abc doc no| con|an cncr,p|cd da|a, |hc
SECUREFILE cauc mu| bc ucd.
\hen you udd dutu to the LC, t w be uutomutcuy compressed by the dutubuse,
smury, when you reud dutu lrom u LC, t w be uutomutcuy decompressed. You cun use
COMPRESS HIGH lor muxmum dutu compresson, the deluut s COMPRESS MEDIUM, und the
MEDIUM keyword s optonu. 1he hgher the compresson, the hgher the overheud when reudng
und wrtng LC dutu.
Rcmuving DupIicatc lOB Data
You cun conlgure u BLOB, CLOB, or NCLOB so thut uny dupcute dutu supped to t s uutomutcuy
removed, ths process s known us de-dupcutng dutu und cun suve storuge spuce. lor exumpe,
the loowng stutement creutes u tube wth u CLOB whose contents ure to be de-dupcuted,
notce the use ol the DEDUPLICATE LOB keywords:
CREATE TABLE clob_content2 (
id INTEGER PRIMARY KEY,
clob_column CLOB
) LOB(clob_column) STORE AS SECUREFILE (
DEDUPLICATE LOB
CACHE
);
Any dupcute dutu udded to the LC w be uutomutcuy removed by the dutubuse. 1he
dutubuse uses the SHAl secure hush ugorthm to detect dupcute dutu.
You cun eurn even more ubout urge obects n the Cracc Da|abac argc Cb]cc|
Dcvcopcr' Cudc pubshed by Cruce Corporuton.
Summary
ln ths chupter, you huve eurned the loowng:
LCs muy be used to store bnury dutu, churucter dutu, und relerences to externu les.
LCs cun store up to l28 terubytes ol dutu.

Cruce Dutubuse ll SQL
1here ure lour LC types: CLOB, NCLOB, BLOB, und BFILE.
A CLOB stores churucter dutu.
An NCLOB stores mutpe byte churucter dutu.
A BLOB stores bnury dutu.
A BFILE stores u ponter to u le ocuted n the le system.
A LC conssts ol two purts: u ocutor, whch specles the ocuton ol the LC dutu, und
the dutu tsel.
1he DBMS_LOB lL/SQL puckuge contuns methods lor uccessng LCs.
ln the next chupter, you' eurn how to run SQL stutements lrom u }uvu progrum.
\IAI1II
1
Runnng SQL Lsng }uvu
53l
S32
Cruce Dutubuse llg SQL
n ths chupter, you w do the loowng:
Leurn how to run SQL lrom }uvu progrums usng the }uvu Dutubuse Connectvty (}DC)
Appcuton lrogrummng lnterluce (All)
Lxumne the vurous Cruce }DC drvers thut muy be used to connect to un Cruce
dutubuse
lerlorm queres und SQL DML stutements to uccess dutubuse tubes
Lse the vurous }uvu types to get und set coumn vuues n the dutubuse
Lxumne how to perlorm trunsucton contro stutements und SQL DDL stutements
Hunde dutubuse exceptons thut muy occur when u }uvu progrum runs
Lxumne the Cruce dutubuse soltwure extensons to }DC
See compete }uvu progrums thut ustrute the use ol }DC
NOTf
Th chap|cr gvc an n|roduc|on |o }DC. or |u dc|a on ung
}DC v|h an Cracc da|abac, ,ou houd rcad m, boo| Cruce9
}DC lrogrummng (\cCrav-H/Cbornc, 2002).
Gctting Startcd
lror to runnng the exumpes n ths chupter, you' need to nstu u verson ol Sun's }uvu Soltwure
Deveopment Kt (SDK). You cun downoud the SDK und vew lu nstuuton nstructons lrom
Sun's }uvu webste ut uvu.sun.com.
NOTf
ucd }ava 1..0 vhcn vr|ng |h chap|cr, vhch n|acd v|h }ava
SDK Lpda|c 2.
1he drectory where you nstued the Cruce soltwure on your muchne s cued the
CRACLL_HCML drectory. Cn my \ndows computer, ths drectory s L:\oruce_llg\
product\ll.l.0\dbl. lnsde CRACLL_HCML ure muny subdrectores, one ol whch s the
dbc drectory. 1he dbc drectory contuns the loowng:
A text le numed Reudme.txt. You shoud open und reud ths le, us t contuns mportunt
tems such us reeuse nlormuton und the utest nstuuton nstructons.
A drectory numed b, whch contuns u number ol }uvu Archve (}AR) les.

Chupter l5: Runnng SQL Lsng }uvu


S33
Cunfiguring Yuur Cumputcr
Cnce you've downouded und nstued the requred soltwure, your next step s to conlgure your
computer to deveop und run }uvu progrums contunng }DC stutements. You must set lour
envronment vurubes on your muchne:
ORACLE_HOME
JAVA_HOME
PATH
CLASSPATH
ll you're usng Lnx or Lnux, you' uso need to set the uddtonu LD_LIBRARY_PATH
envronment vurube. You' eurn how to set these envronment vurubes n the loowng
sectons.
CAUTlON
Thc n|orma|on n |h cc|on va corrcc| a| |mc o| vr|ng. You nccd
|o rcad |hc Rcadmc.|x| |c n |hc CRAC_HC\']dbc drcc|or, |o
chcc| |hc a|c| rccac no|c and n|aa|on n|ruc|on.
Sctting thc ORAClf_HOMf fnvirunmcnt VariabIc
1he CRACLL_HCML subdrectory s ocuted n the drectory where you nstued the Cruce
soltwure. You' need to set un envronment vurube numed ORACLE_HOME on your muchne
thut specles ths drectory.
Sctting an fnvirunmcnt VariabIc in Winduws XP
1o set un envronment vurube n \ndows Xl, you perlorm the loowng steps:
1. Cpen the Contro lune.
2. Doube-cck System. 1hs dspuys the System lropertes duog box.
3. Seect the Advunced tub.
4. Cck the Lnvronment Vurubes button. 1hs dspuys the Lnvronment Vurubes duog box.
S. Cck the New button n the System Vurubes ureu (the ower pune ol the duog box).
6. Set the vurube nume to ORACLE_HOME und set the vuue to your CRACLL_HCML
drectory. (Cn my \ndows Xl muchne, l huve ORACLE_HOME set to L:\oruce_llg\
product\ll.l.0\dbl.)
Sctting an fnvirunmcnt VariabIc with Unix ur linux
1o set un envronment vurube n Lnx or Lnux, you need to udd nes to u specu le, the le
you need to modly depends on whch she you're usng. ll you're usng the ourne, Korn, or
ush she, then you udd nes smur to the loowng ones to your .prole (when usng ourne
or Korn she) or your .bush_prole (ush she):
ORACLE_HOME=/u01/app/oracle/product/11.1.0/db_1
export ORACLE_HOME
S34
Cruce Dutubuse llg SQL
NOTf
You' nccd |o rcpacc |hc drcc|or, hovn n |hc prcvou cxampc
v|h |hc corrcc| CRAC_HC\ |or ,our c|up.
ll you're usng the C she, you udd the loowng ne to your .ogn le:
setenv ORACLE_HOME /u01/app/oracle/product/11.1.0/db_1
Sctting thc |AVA_HOMf fnvirunmcnt VariabIc
1he JAVA_HOME envronment vurube specles the drectory where you nstued the }uvu SDK.
lor exumpe, l you nstued the }uvu SDK n the L:\uvu\dk drectory, you creute u JAVA_HOME
system vurube und set t to L:\uvu\dk. 1o do ths, you cun use smur steps to those shown n
the prevous secton.
Sctting thc PATH fnvirunmcnt VariabIc
1he PATH envronment vurube contuns u st ol drectores. \hen you enter u commund usng
the operutng system commund ne, the computer seurches the drectores n the PATH lor the
executube you ure tryng to run. You need to udd the loowng two drectores to your exstng
PATH:
1he bn subdrectory where you nstued the }uvu SDK
1he lN subdrectory ol CRACLL_HCML
lor exumpe, l you nstued the }uvu SDK n the L:\uvu\dk drectory, und your CRACLL_
HCML s L:\oruce_llg\product\ll.l.0\dbl, then you udd L:\uvu\dk\bn, L:\oruce_llg\
product\ll.l.0\dbl to your PATH (notce u semcoon sepurutes the two drectores). 1o udd
the drectores to the PATH n \ndows Xl, you cun use steps smur to those shown eurer.
1o udd to un exstng PATH n Lnx or Lnux, you need to modly the upproprute le lor your
she. lor exumpe, l you're usng the ush she wth Lnux, then you udd nes to the .bush_
prole le thut ure smur to the loowng:
PATH=$PATH:$JAVA_HOME/bin:$ORACLE_HOME/BIN
export PATH
Notce thut u coon (:) sepurutes the drectores.
Sctting thc ClASSPATH fnvirunmcnt VariabIc
1he CLASSPATH envronment vurube contuns u st ol ocutons where }uvu cuss puckuges ure
lound. A ocuton cun be u drectory nume or the nume ol u Zp le or }AR le contunng cusses.
1he CRACLL_HCML\dbc\b drectory contuns u number ol }AR les, whch ones you udd to
your CLASSPATH depends on whut }uvu SDK you're usng.
At tme ol wrtng, the loowng wus correct lor settng u CLASSPATH:
ll you're usng }DK l.6 (or hgher), udd CRACLL_HCML\dbc\b\odbc6.ur to your
CLASSPATH.
ll you're usng }DK l.5, udd CRACLL_HCML\dbc\b\odbc5.ur to your CLASSPATH.
ll you need Nutonu Lunguuge support, udd CRACLL_HCML\b\orul8n.ur to your
CLASSPATH.
Chupter l5: Runnng SQL Lsng }uvu
S3S
ll you need the }1A und }NDl leutures, udd CRACLL_HCML\b\tu.ur und CRACLL_
HCML\b\nd.ur to your CLASSPATH. }NDl s the }ava ^amng and Drcc|or, n|cr|acc.
}1A s the }ava Tranac|on A.
You uso need to udd the current drectory to your CLASSPATH. You do ths by uddng
u perod (.) to your CLASSPATH. 1hut wuy, the cusses n your current drectory w be
lound by }uvu when you run your progrums.
\hen }uvu l.6 s used und the CRACLL_HCML s L:\oruce_llg\product\ll.l.0\dbl, un
exumpe CLASSPATH lor \ndows Xl s us loows:
.;E:\oracle_11g\product\11.1.0\db1\jdbc\lib\ojdbc6.jar;
E:\oracle_11g\product\11.1.0\db1\jlib\orai18n.jar
ll you're usng \ndows Xl, you use the steps descrbed eurer to creute u system
envronment vurube cued CLASSPATH. ll you're usng Lnux und }uvu l.6, you shoud udd the
loowng nes to your .bush_prole:
CLASSPATH=$CLASSPATH:.:$ORACLE_HOME/jdbc/lib/ojdbc6.jar:
$ORACLE_HOME/jlib/orai18n.jar
export CLASSPATH
Sctting thc lD_llBRARY_PATH fnvirunmcnt VariabIc
ll you're usng Lnx or Lnux, you' uso need to set the LD_LIBRARY_PATH envronment vurube
to SCRACLL_HCML/dbc/b. 1hs drectory contuns shured brures thut ure used by the }DC
CCl drver. You udd LD_LIBRARY_PATH to the upproprute le, lor exumpe:
LD_LIBRARY_PATH=$ORACLE_HOME/jdbc/lib
export CLASSPATH
1hut concudes conlgurng your computer. You' eurn ubout the Cruce }DC drvers next.
Thc OracIc |DBC Drivcrs
ln ths secton, you' eurn ubout the vurous Cruce }DC drvers. 1hese drvers enube the }DC
stutements n u }uvu progrum to uccess un Cruce dutubuse. 1here ure lour Cruce }DC drvers:
1hn drver
CCl drver
Server-sde nternu drver
Server-sde 1hn drver
1he loowng sectons descrbe euch ol these drvers.
Thc Thin Drivcr
1he 1hn drver hus the smuest lootprnt ol u the drvers, meunng thut t requres the eust
umount ol system resources to run. 1he 1hn drver s wrtten entrey n }uvu. ll you ure wrtng u
}uvu uppet, you shoud use the 1hn drver. 1he 1hn drver muy uso be used n stund-uone }uvu
S36
Cruce Dutubuse llg SQL
uppcutons und muy be used to uccess u versons ol the Cruce dutubuse. 1he 1hn drver works
ony wth 1Cl/ll und requres thut Cruce Net be up und runnng. lor detus on Cruce Net, you
cun reud the Cracc Da|abac ^c| Scrvcc Admn|ra|or' Cudc pubshed by Cruce Corporuton.
NOTf
You don'| havc |o n|a an,|hng on |hc ccn| compu|cr |o uc |hc
Thn drvcr, and |hcrc|orc ,ou can uc | |or appc|.
Thc OCl Drivcr
1he CCl drver requres more resources thun the 1hn drver, but t generuy hus better perlormunce.
1he CCl drver s sutube lor progrums depoyed on the mdde teru web server, lor exumpe.
NOTf
Thc CC drvcr rcqurc |ha| ,ou n|a | on |hc ccn| compu|cr and
|hcrc|orc no| u|abc |or appc|.
1he CCl drver hus u number ol perlormunce enhuncng leutures, ncudng the ubty to poo
dutubuse connectons und preletch rows lrom the dutubuse. 1he CCl drver works wth u versons
ol the dutubuse und u ol the supported Cruce Net protocos.
Thc Scrvcr-Sidc lntcrnaI Drivcr
1he server-sde nternu drver provdes drect uccess to the dutubuse, und t s used by the Cruce
}VM to communcute wth thut dutubuse 1he Cruce }VM s u }uvu Vrtuu Muchne thut s ntegruted
wth the dutubuse. You cun oud u }uvu cuss nto the dutubuse, then pubsh und run methods
contuned n thut cuss usng the Cruce }VM, the }uvu code runs on the dutubuse server und cun
uccess dutu lrom u snge Cruce sesson.
Thc Scrvcr-Sidc Thin Drivcr
1he server-sde 1hn drver s uso used by the Cruce }VM und provdes uccess to remote dutubuses.
Lke the 1hn drver, ths drver s uso wrtten entrey n }uvu. }uvu code thut uses the server-sde
1hn drver cun uccess unother sesson on the sume dutubuse server or u remote server.
lmpurting thc |DBC Packagcs
ln order lor your progrums to use }DC, you must mport the requred }DC puckuges nto your
}uvu progrums. 1here ure two sets ol }DC puckuges:
Stundurd }DC puckuges lrom Sun Mcrosystems
Lxtenson puckuges lrom Cruce Corporuton
1he stundurd }DC puckuges enube your }uvu progrums to uccess the busc leutures ol most
dutubuses, ncudng the Cruce dutubuse, SQL Server, D2, und MySQL. 1he Cruce extensons
to }DC enube your progrums to uccess u ol the Cruce-speclc leutures us we us the Cruce-
speclc perlormunce extensons. You' eurn ubout some ol the Cruce-speclc leutures uter n
ths chupter.
Chupter l5: Runnng SQL Lsng }uvu
S37
1o use }DC n your progrums you shoud mport the stundurd java.sql.* puckuges, us
shown n the loowng import stutement:
import java.sql.*;
Cl course, mportng java.sql.* mports ol the stundurd }DC puckuges. As you
become prolcent n }DC, you' lnd thut you don't uwuys need to mport u the cusses: you
cun ust mport those puckuges thut your progrum uctuuy uses.
Rcgistcring thc OracIc |DBC Drivcrs
elore you cun open u dutubuse connecton, you must lrst regster the Cruce }DC drvers wth
your }uvu progrum. As mentoned eurer, the }DC drvers enube your }DC stutements to uccess
the dutubuse.
1here ure two wuys to regster the Cruce }DC drvers:
Lse the forName() method ol the cuss java.lang.Class
Lse the registerDriver() method ol the }DC DriverManager cuss
1he loowng exumpe ustrutes the use ol the forName() method:
Class.forName("oracle.jdbc.OracleDriver");
1he second wuy to regster the Cruce }DC drvers s to use the registerDriver()
method ol the java.sql.DriverManager cuss, us shown n the loowng exumpe:
DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
Cnce you huve regstered the Cruce }DC drvers, you cun open u connecton to u dutubuse.
Opcning a Databasc Cunncctiun
elore you cun ssue SQL stutements n your }uvu progrums, you must open u dutubuse
connecton. 1here ure two mun wuys to open u dutubuse connecton:
Lse the getConnection() method ol the DriverManager cuss
Lse un Cruce dutu source obect, whch must lrst be creuted und then connected to. 1hs
method uses u stundurdzed wuy ol settng dutubuse connecton detus, und un Cruce
dutu source obect muy be used wth the }uvu Numng und Drectory lnterluce (}NDl).
l' descrbe both ol these wuys to open u dutubuse connecton n the loowng sectons,
sturtng wth the getConnection() method ol the DriverManager cuss.
Cunnccting tu thc Databasc Using gctCunncctiun()
1he getConnection() method returns u }DC Connection obect, whch shoud be stored n
your progrum so t cun be relerenced uter. 1he syntux ol u cu to the getConnection() method
s us loows:
DriverManager.getConnection(URL, username, password);
S38
Cruce Dutubuse ll SQL
where
URL s the dutubuse thut your progrum connects to, uong wth the }DC drver you wunt
to use. (See the loowng secton, 1he Dutubuse LRL, lor detus on the LRL.)
username s the nume ol the dutubuse user thut your progrum connects us.
password s the pussword lor the usernume.
1he loowng exumpe shows the getConnection() method beng used to connect to u
dutubuse:
Connection myConnection = DriverManager.getConnection(
"jdbc:oracle:thin:@localhost:1521:ORCL",
"store",
"store_password"
);
ln ths exumpe, the connecton s mude to u dutubuse runnng on the muchne dentled us
localhost wth un Cruce System ldentler (SlD) ol ORCL, the Cruce }DC 1hn drver s used.
1he connecton s mude wth the usernume store und the pussword store_password. 1he
Connection obect returned by the cu to getConnection() s stored n myConnection.
1he connecton to u dutubuse s mude through Cruce Net, whch shoud be up und runnng
when the progrum ne s run.
Thc Databasc URl
1he dutubuse LRL specles the ocuton ol the dutubuse. 1he structure ol the dutubuse LRL s
dependent on the vendor who provdes the }DC drvers. ln the cuse ol Cruce's }DC drvers,
the dutubuse LRL structure s us loows:
driver_name:@driver_information
where
driver_name s the nume ol the Cruce }DC drver thut your progrum uses. 1hs muy
be set to one ol the loowng:
jdbc:oracle:thin 1he Cruce }DC 1hn drver
jdbc:oracle:oci 1he Cruce }DC CCl drver
driver_information 1he drver-speclc nlormuton requred to connect to the
dutubuse. 1hs s dependent on the drver beng used. ln the cuse ol the Cruce }DC
1hn drver, the drver-speclc nlormuton muy be specled n the loowng lormut:
host_name:port:database_SID \here host_name s the nume ol the
computer, port s the port to uccess the dutubuse, und database_SID s the
dutubuse SlD
lor u the Cruce }DC drvers, ncudng the 1hn drver und the vurous CCl drvers, the
drver-speclc nlormuton muy uso be specled usng Cruce Net keyword-vuue purs, whch
muy be specled n the loowng lormut:
Chupter l5: Runnng SQL Lsng }uvu
S39
(description=(address=(host=host_name)(protocol=tcp)(port=port))
(connect_data=(sid=database_SID)))
where
host_name s the nume ol the computer on whch the dutubuse s runnng.
port s the port number on whch the Cruce Net dutubuse stener wuts lor requests,
l52l s the deluut port number. Your DA cun provde the port number.
database_SID s the Cruce SlD ol the dutubuse nstunce to whch you wunt to
connect. Your DA cun provde the dutubuse SlD.
1he loowng exumpe shows the getConnection() method beng used to connect to u
dutubuse usng the Cruce CCl drver, wth the drver-speclc nlormuton specled usng Cruce
Net keyword-vuue purs:
Connection myConnection = DriverManager.getConnection(
"jdbc:oracle:oci:@(description=(address=(host=localhost)" +
"(protocol=tcp)(port=1521))(connect_data=(sid=ORCL)))",
"store",
"store_password"
);
As you cun see, n ths exumpe u connecton s mude to u dutubuse runnng on the muchne
dentled us localhost, wth un Cruce SlD ol ORCL, usng the Cruce CCl drver. 1he
connecton to the dutubuse s mude wth the usernume store und wth u pussword ol store_
password. 1he Connection obect returned by the cu to getConnection() s stored n
myConnection.
NOTf
or |hc Cracc CC drvcr, ,ou ma, ao uc an Cracc ^c| T^S^A\S
|rng. or morc n|orma|on on |h, pca| v|h ,our DA or conu|
|hc Cruce Dutubuse Net Servces Admnstrutor's Cude pubhcd b,
Cracc Corpora|on.
Cunnccting tu thc Databasc Using an OracIc Data Suurcc
You cun uso use un Cruce da|a ourcc to connect to u dutubuse. An Cruce dutu source uses u
more stundurdzed wuy ol suppyng the vurous purumeters to connect to u dutubuse thun the
prevous method, whch used DriverManager.getConnection(). ln uddton, un Cruce
dutu source muy uso be regstered wth }NDl. Lsng }NDl wth }DC s very uselu, becuuse t
uows you to regster, or bnd, dutu sources, und then oo| up those dutu sources n your progrum
wthout huvng to provde the exuct dutubuse connecton detus. 1hus, l the dutubuse connecton
detus chunge, ony the }NDl obect must be chunged.
NOTf
You can carn abou| }^D n m, boo| Cruce9 }DC lrogrummng
(\cCrav-H/Cbornc, 2002).
S40
Cruce Dutubuse ll SQL
1here ure three steps thut must be perlormed to use un Cruce dutu source:
1. Creute un Cruce dutu source obect ol the oracle.jdbc.pool.OracleDataSource
cuss.
2. Set the Cruce dutu source obect uttrbutes usng the set methods, whch ure delned n
the cuss.
3. Connect to the dutubuse vu the Cruce dutu source obect usng the getConnection()
method.
1he loowng sectons descrbe these three steps.
Stcp 1: Crcatc an OracIc Data Suurcc Objcct
1he lrst step s to creute un Cruce dutu source obect ol the oracle.jdbc.pool
.OracleDataSource cuss. 1he loowng exumpe creutes un OracleDataSource obect
numed myDataSource (you muy ussume thut the oracle.jdbc.pool.OracleDataSource
cuss hus been mported):
OracleDataSource myDataSource = new OracleDataSource();
Cnce you huve your OracleDataSource obect, the second step s to set thut obect's
uttrbutes usng the set methods.
Stcp 2: Sct thc OracIc Data Suurcc Objcct Attributcs
elore you cun use your OracleDataSource obect to connect to u dutubuse, you must set u
number ol uttrbutes n thut obect to ndcute the connecton detus, usng vurous set methods
delned n the cuss. 1hese detus ncude tems ke the dutubuse nume, the }DC drver to use,
und so on, euch ol these detus hus u correspondng uttrbute n un OracleDataSource obect.
1he oracle.jdbc.pool.OracleDataSource cuss uctuuy mpements the javax
.sql.DataSource nterluce provded wth }DC. 1he javax.sql.DataSource nterluce
delnes u number ol uttrbutes, whch ure sted n 1ube l5-l. 1hs tube shows the nume,
descrpton, und type ol euch uttrbute.
1he oracle.jdbc.pool.OracleDataSource cuss provdes un uddtonu set ol
uttrbutes, whch ure sted n 1ube l5-2.
You muy use u number ol methods to reud lrom und wrte to euch ol the uttrbutes sted n
1ubes l5-l und l5-2. 1he methods thut reud lrom the uttrbutes ure known us methods, und
the methods thut wrte to the uttrbutes ure known us methods.
1he set und get method numes ure eusy to remember: you tuke the uttrbute nume, convert
the lrst etter to uppercuse, und udd the word set or get to the begnnng. lor exumpe, to set
the dutubuse nume (stored n the databaseName uttrbute), you use the setDatabaseName()
method, to get the nume ol the dutubuse currenty set, you use the getDatabaseName()
method. 1here s one excepton to ths: there s no getPassword() method (ths s lor securty
reusonsyou don't wunt someone to be ube to get your pussword progrummutcuy).
Most ol the uttrbutes ure }uvu String obects, so most ol the set methods uccept u snge
String purumeter, und most ol the get methods return u String. 1he excepton to ths s the
portNumber uttrbute, whch s un int. 1herelore, ts set method setPortNumber()
uccepts un int, und ts get method getPortNumber() returns un int.
Chupter l5: Runnng SQL Lsng }uvu
S41
Attributc Namc Attributc Dcscriptiun Attributc Typc
databaseName
1he dutubuse nume (Cruce SlD).
String
dataSourceName
1he nume ol the underyng dutu source cuss.
String
description
Descrpton ol the dutu source.
String
networkProtocol
1he network protoco to use to communcute
wth the dutubuse. 1hs uppes ony to the Cruce
}DC CCl drvers, und deluuts to tcp. lor lurther
detus, reud the Cracc Da|abac ^c| Scrvcc
Admn|ra|or' Cudc pubshed by Cruce
Corporuton.
String
password
1he pussword lor the supped usernume.
String
portNumber
1he port on whch the Cruce Net stener wuts lor
dutubuse connecton requests. 1he deluut s l52l.
int
serverName
1he dutubuse server muchne nume (1Cl/ll
uddress or DNS uus).
String
user
1he dutubuse usernume.
String
TABlf 1S-1 DataSource A||rbu|c
Attributc Namc Attributc Dcscriptiun Attributc Typc
driverType
1he }DC drver to use. ll you ure usng the
server-sde nternu drver, ths s set to kprb,
und the other settngs lor the uttrbutes ure
gnored.
String
url
Muy be used to specly un Cruce dutubuse
LRL, whch cun be used us un uternutve to
settng the dutubuse ocuton. See the secton
eurer on dutubuse LRLs lor detus.
String
tnsEntryName
Muy be used to specly un Cruce Net
1NSNAMLS strng, whch cun uso be used to
specly the dutubuse ocuton when usng the
CCl drvers.
String
TABlf 1S-2 OracleDataSource A||rbu|c
S42
Cruce Dutubuse ll SQL
1he loowng exumpes ustrute the use ol the set methods to wrte to the uttrbutes ol the
OracleDataSource obect myDataSource thut wus creuted eurer n Step l:
myDataSource.setServerName("localhost");
myDataSource.setDatabaseName("ORCL");
myDataSource.setDriverType("oci");
myDataSource.setNetworkProtocol("tcp");
myDataSource.setPortNumber(1521);
myDataSource.setUser("scott");
myDataSource.setPassword("tiger");
1he next exumpes ustrute the use ol some ol the get methods to reud the uttrbutes
prevousy set n myDataSource:
String serverName = myDataSource.getServerName();
String databaseName = myDataSource.getDatabaseName();
String driverType = myDataSource.getDriverType();
String networkProtocol = myDataSource.getNetworkProtocol();
int portNumber = myDataSource.getPortNumber();
Cnce you've set your OracleDataSource obect uttrbutes, you cun use t to connect to the
dutubuse.
Stcp 3: Cunncct tu thc Databasc via thc OracIc Data Suurcc Objcct
1he thrd step s to connect to the dutubuse vu the OracleDataSource obect. You do
ths by cung the getConnection() method ol your OracleDataSource obect. 1he
getConnection() method returns u }DC Connection obect, whch must be stored.
1he loowng exumpe shows how to cu the getConnection() method usng the
myDataSource obect popuuted n the prevous step:
Connection myConnection = myDataSource.getConnection();
1he Connection obect returned by getConnection() s stored n myConnection. You
cun uso puss u usernume und pussword us purumeters to the getConnection() method, us
shown n the loowng exumpe:
Connection myConnection = myDataSource.getConnection(
"store", "store_password"
);
ln ths exumpe, the usernume und pussword w overrde the usernume und pussword
prevousy set n myDataSource. 1herelore, the connecton to the dutubuse w be mude usng
the usernume ol store wth u pussword ol store_password, ruther thun scott und tiger,
whch were set n myDataSource n the prevous secton.
Cnce you huve your Connection obect, you cun use t to creute u }DC Statement obect.
Crcating a |DBC Statcmcnt Objcct
Next, you need to creute u }DC Statement obect ol the cuss java.sql.Statement. A
Statement obect s used to represent un SQL stutement, such us u query, u DML stutement
(INSERT, UPDATE, or DELETE), or u DDL stutement (such us CREATE TABLE). You' eurn how
to ssue queres, DML, und DDL stutements uter n ths chupter.
Chupter l5: Runnng SQL Lsng }uvu
S43
1o creute u Statement obect, you use the createStatement() method ol u Connection
obect. ln the loowng exumpe, u Statement obect numed myStatement s creuted usng
the createStatement() method ol the myConnection obect creuted n the prevous secton:
Statement myStatement = myConnection.createStatement();
1he method used n the Statement cuss to run the SQL stutement w depend on the SQL
stutement you wunt to perlorm. ll you wunt to perlorm u query, you use the executeQuery()
method. ll you wunt to perlorm un INSERT, UPDATE, or DELETE stutement, you use the
executeUpdate() method. ll you don't know uheud ol tme whch type ol SQL stutement s
to be perlormed, you cun use the execute() method, whch muy be used to perlorm uny SQL
stutement.
1here s unother }DC cuss thut muy be used to represent un SQL stutement: the
PreparedStatement cuss. 1hs ollers more udvunced lunctonuty thun the Statement
cuss, l w dscuss the PreparedStatement cuss ulter l huve expuned the use ol the
Statement cuss.
Cnce you huve u Statement obect, you're reudy to ssue SQL stutements usng }DC.
Rctricving Ruws frum thc Databasc
1o perlorm u query usng }DC, you use the executeQuery() method ol the Statement
obect, whch uccepts u }uvu String contunng the text lor the query.
ecuuse u query muy return more thun one row, the executeQuery() method returns un
obect thut stores the row(s) returned by your query. 1hs obect s known us u }DC und
s ol the java.sql.ResultSet cuss. \hen usng u ResultSet obect to reud rows lrom the
dutubuse, there ure three steps you loow:
1. Creute u ResultSet obect und popuute t wth the resuts returned by u query.
2. Reud the coumn vuues lrom the ResultSet obect usng get methods.
3. Cose the ResultSet obect.
l w now wuk you through un exumpe thut uses u ResultSet obect to retreve the rows
lrom the customers tube.
Stcp 1: Crcatc and PupuIatc a RcsuItSct Objcct
You lrst creute u ResultSet obect und popuute t wth the resuts returned by u query. 1he
loowng exumpe creutes u ResultSet obect numed customerResultSet und popuutes
t wth the customer_id, first_name, last_name, dob, und phone coumns lrom the
customers tube:
ResultSet customerResultSet = myStatement.executeQuery(
"SELECT customer_id, first_name, last_name, dob, phone " +
"FROM customers"
);
Alter ths stutement s executed, the ResultSet obect w contun the coumn vuues lor
the rows retreved by the query. 1he ResultSet obect muy then be used to uccess the coumn
vuues lor the retreved rows. ln the exumpe, customerResultSet w contun the lve rows
retreved lrom the customers tube.
S44
Cruce Dutubuse llg SQL
ecuuse the execute() method uccepts u }uvu String, you cun bud up your SQL
stutements when your progrum uctuuy runs. 1hs meuns thut you cun do some lury powerlu
thngs n }DC. lor exumpe, you coud huve the user ol your progrum type n u strng contunng
u WHERE cuuse lor u query when they run the progrumor even enter the whoe query. 1he
loowng exumpe shows u WHERE cuuse strng:
String whereClause = "WHERE customer_id = 1";
ResultSet customerResultSet2 = myStatement.executeQuery(
"SELECT customer_id, first_name, last_name, dob, phone " +
"FROM customers " +
whereClause
);
You're not mted to queres n usng ths dynumc bud-up method: you cun bud up other
SQL stutements n u smur munner.
Stcp 2: Rcad thc CuIumn VaIucs frum thc RcsuItSct Objcct
1o reud the coumn vuues lor the rows stored n u ResultSet obect, the ResultSet cuss
provdes u seres ol get methods. elore l get nto the detus ol these get methods, you need to
understund how the dutu types used to represent vuues n Cruce muy be mupped to computbe
}uvu dutu types.
OracIc and |ava Typcs
A }uvu progrum uses u dllerent set ol types lrom the Cruce dutubuse types to represent vuues.
lortunutey, the types used by Cruce ure computbe wth certun }uvu types. 1hs uows }uvu und
Cruce to nterchunge dutu stored n ther respectve types. 1ube l5-3 shows one set ol computbe
type muppngs.
lrom ths tube, you cun see thut un Cruce INTEGER s computbe wth u }uvu int. (l' tuk
ubout the other numerc types uter n ths chupter n the secton Hundng Numbers.) 1hs meuns
thut the customer_id coumn ol the customers tube (whch s delned us un Cruce INTEGER)
OracIc Typc |ava Typc
CHAR String
VARCHAR2 String
DATE java.sql.Date
java.sql.Time
java.sql.Timestamp
INTEGER short
int
long
NUMBER float
double
java.math.BigDecimal
TABlf 1S-3 Compa|bc T,pc \appng
Chupter l5: Runnng SQL Lsng }uvu
S4S
muy be stored n u }uvu int vurube. Smury, the first_name, last_name, und phone
coumn vuues (VARCHAR2s) muy be stored n }uvu String vurubes.
1he Cruce DATE type stores u yeur, month, duy, hour, mnute, und second. You muy use u
java.sql.Date obect to store the dute purt ol the dob coumn vuue und u java.sql.Time
vurube to store the tme purt. You muy uso use u java.sql.Timestamp obect to store both
the dute und tme purts ol the dob coumn. Luter n ths chupter, l' dscuss the oracle.sql
.DATE type, whch s un Cruce extenson to the }DC stundurd und provdes u superor wuy ol
storng dutes und tmes.
Cettng buck to the exumpe, the customer_id, first_name, last_name, dob, und
phone coumns ure retreved by the query n the prevous secton, und the loowng exumpes
decure }uvu vurubes und obects thut ure computbe wth those coumns:
int customerId = 0;
String firstName = null;
String lastName = null;
java.sql.Date dob = null;
String phone = null;
1he int und String types ure purt ol the core }uvu unguuge, whe java.sql.Date s
purt ol }DC und s un extenson ol the core }uvu unguuge. }DC provdes u number ol such types
thut uow }uvu und u reutonu dutubuse to exchunge dutu. However, }DC doesn't huve types to
hunde u ol the types used by Cruce, one exumpe s the ROWID typeyou must use the
oracle.sql.ROWID type to store un Cruce ROWID.
1o hunde u ol the Cruce types, Cruce provdes u number ol uddtonu types, whch ure
delned n the oracle.sql puckuge. Aso, Cruce hus u number ol types thut muy be used us
un uternutve to the core }uvu und }DC types, und n some cuses these uternutves oller more
lunctonuty und better perlormunce thun the core }uvu und }DC types. l' tuk more ubout the
Cruce types delned n the oracle.sql puckuge uter n ths chupter.
Now thut you understund u tte bt ubout computbe }uvu und Cruce types, et's contnue
wth the exumpe und see how to use the get methods to reud coumn vuues.
Using thc Gct Mcthuds tu Rcad CuIumn VaIucs
1he get methods ure used to reud vuues stored n u ResultSet obect. 1he nume ol euch get
method s smpe to understund: tuke the nume ol the }uvu type you wunt the coumn vuue to be
returned us und udd the word get to the begnnng. lor exumpe, use getInt() to reud u coumn
vuue us u }uvu int, und use getString() to reud u coumn vuue us u }uvu String. 1o reud
the vuue us u java.sql.Date, you woud use getDate(). Luch get method uccepts one
purumeter: ether un int representng the poston ol the coumn n the orgnu query or u String
contunng the nume ol the coumn. Let's exumne some exumpes bused on the eurer exumpe
thut retreved the coumns lrom the customers tube n the customerResultSet obect.
1o get the vuue ol the customer_id coumn, whch wus the lrst coumn specled n the
query, you use getInt(1). You cun uso use the nume ol the coumn n the get method, so
you coud uso use getInt("customer_id") to get the sume vuue.
TlP
Lng |hc coumn namc ra|hcr |han |hc coumn po|on numbcr n a
get mc|hod ma|c ,our codc cacr |o rcad.
S46
Cruce Dutubuse ll SQL
1o get the vuue ol the first_name coumn, whch wus the second coumn specled n the
query, you use getString(2) or getString("first_name"). You use smur method cus
to get the last_name und phone coumn vuues becuuse those coumns ure uso text strngs. 1o
get the vuue ol the dob coumn, you coud use getDate(4) or getDate("dob"). 1o uctuuy
reud the vuues stored n u ResultSet obect, you must cu the get methods usng thut
ResultSet obect.
ecuuse u ResultSet obect muy contun more thun one row, }DC provdes u method
numed next() thut uows you to step through euch row stored n u ResultSet obect. You
must cu the next() method to uccess the lrst row n the ResultSet obect, und euch
successve cu to next() steps to the next row. \hen there ure no more rows n the
ResultSet obect to reud, the next() method returns the ooeun false vuue.
Ckuy, et's get buck to our exumpe: we huve u ResultSet obect numed
customerResultSet thut hus lve rows contunng the coumn vuues retreved lrom
the customer_id, first_name, last_name, dob, und phone coumns n the customers
tube. 1he loowng exumpe shows u while oop thut reuds the coumn vuues lrom
customerResultSet nto the customerId, firstName, lastName, dob, und phone
obects creuted eurer:
while (customerResultSet.next()) {
customerId = customerResultSet.getInt("customer_id");
firstName = customerResultSet.getString("first_name");
lastName = customerResultSet.getString("last_name");
dob = customerResultSet.getDate("dob");
phone = customerResultSet.getString("phone");
System.out.println("customerId = " + customerId);
System.out.println("firstName = " + firstName);
System.out.println("lastName = " + lastName);
System.out.println("dob = " + dob);
System.out.println("phone = " + phone);
} // end of while loop
\hen there ure no more rows to reud lrom customerResultSet, the next() method
returns false und the oop termnutes. You' notce thut the exumpe pusses the nume ol the
coumn to be reud, ruther thun numerc postons, to the get methods. Aso, l've coped
the coumn vuues nto }uvu vurubes und obects, lor exumpe, the vuue returned lrom
customerResultSet.getInt("customer_id") s coped to customerId. You don't
huve to do thut copy: you coud smpy use the get method cu whenever you need the vuue.
However, t s generuy better l you copy t to u }uvu vurube or obect, becuuse t w suve tme
l you use thut vuue more thun once (the tme s suved becuuse you don't huve to cu the get
method ugun).
Stcp 3: CIusc thc RcsuItSct Objcct
Cnce you've lnshed wth your ResultSet obect, you must cose thut ResultSet obect
usng the close() method. 1he loowng exumpe coses customerResultSet:
customerResultSet.close();
Chupter l5: Runnng SQL Lsng }uvu
S47
NOTf
| mpor|an| |ha| ,ou rcmcmbcr |o coc ,our ResultSet ob]cc|
oncc ,ou'vc |nhcd v|h |. Dong o cnurc |ha| |hc ob]cc|
chcducd |or garbagc cocc|on.
Now thut you've seen how to retreve rows, l' show you how to udd rows to u dutubuse tube
usng }DC.
Adding Ruws tu thc Databasc
You use the SQL INSERT stutement to udd rows to u tube. 1here ure two mun wuys you cun
perlorm un INSERT stutement usng }DC:
Lse the executeUpdate() method delned n the Statement cuss.
Lse the execute() method delned n the PreparedStatement cuss. (l w dscuss
ths cuss uter n ths chupter.)
1he exumpes n ths secton ustrute how to udd u row to the customers tube. 1he
customer_id, first_name, last_name, dob, und phone coumns lor ths new row w
be set to 6, }uson, lrce, lebruury 22, l969, und 800-555-l2l6, respectvey.
1o udd ths new row, l' use the sume Statement obect decured eurer (myStatement),
uong wth the sume vurubes und obects thut were used to retreve the rows lrom the customers
tube n the prevous secton. lrst oll, l' set those vurubes und obects to the vuues thut l wunt
to set the dutubuse coumns to n the customers tube:
customerId = 6;
firstName = "Jason";
lastName = "Red";
dob = java.sql.Date.valueOf("1969-02-22");
phone = "800-555-1216";
NOTf
Thc java.sql.Date ca |orc da|c ung |hc |orma| YYYY-MM-
DD, vhcrc YYYY |hc ,car, MM |hc mon|h numbcr, and DD |hc
da, numbcr. You can ao uc |hc java.sql.Time and java.sql
.Timestamp cac |o rcprccn| |mc and da|c con|anng |mc,
rcpcc|vc,.
\hen you uttempt to specly u dute n un SQL stutement, you lrst convert t to u lormut thut
the dutubuse cun understund by usng the TO_DATE() but-n dutubuse luncton. TO_DATE()
uccepts u strng contunng u dute, uong wth the lormut lor thut dute. You' see the use ol the
TO_DATE() luncton shorty n the INSERT stutement exumpe. Luter n ths chupter, l' dscuss
the Cruce }DC extensons, und you' see u superor wuy ol representng Cruce-speclc dutes
usng the oracle.sql.DATE type.
\e're reudy to perlorm un INSERT to udd the new row to the customers tube. 1he
myStatement obect s used to perlorm the INSERT stutement, settng the customer_id,
S48
Cruce Dutubuse ll SQL
first_name, last_name, dob, und phone coumn vuues equu to the vuues prevousy
set n the customerId, firstName, lastName, dob, und phone vurubes.
myStatement.executeUpdate(
"INSERT INTO customers " +
"(customer_id, first_name, last_name, dob, phone) VALUES (" +
customerId + ", '" + firstName + "', '" + lastName + "', " +
"TO_DATE('" + dob + "', 'YYYY, MM, DD'), '" + phone + "')"
);
Notce the use ol the TO_DATE() luncton to convert the contents ol the dob obect to un
ucceptube Cruce dutubuse dute. Cnce ths stutement hus competed, the customers tube w
contun the new row.
Mudifying Ruws in thc Databasc
You use the SQL UPDATE stutement to modly exstng rows n u tube. }ust us wth perlormng
un INSERT stutement wth }DC, you cun use the executeUpdate() method delned n the
Statement cuss or the execute() method delned n the PreparedStatement cuss. Lse
ol the PreparedStatement cuss s covered uter n ths chupter.
1he loowng exumpe ustrutes how to modly the row where the customer_id coumn s
equu to l:
first_name = "Jean";
myStatement.executeUpdate(
"UPDATE customers " +
"SET first_name = '" + firstName + "' " +
"WHERE customer_id = 1"
);
Alter ths stutement runs, customer rl's lrst nume w be set to "Jean".
DcIcting Ruws frum thc Databasc
You use the SQL DELETE stutement to deete exstng rows lrom u tube. You cun use the
executeUpdate() method delned n the Statement cuss or the execute() method
delned n the PreparedStatement cuss.
1he loowng exumpe ustrutes how to deete customer r5 lrom the customers tube:
myStatement.executeUpdate(
"DELETE FROM customers " +
"WHERE customer_id = 5"
);
Alter ths stutement runs, the row lor customer r5 w huve been removed lrom the
customers tube.
Chupter l5: Runnng SQL Lsng }uvu
S49
HandIing Numbcrs
1hs secton descrbes the ssues ussocuted wth storng numbers n your }uvu progrums. An Cruce
dutubuse s cupube ol storng numbers wth u precson ol up to 38 dgts. ln the context ol number
representuton, precson relers to the uccurucy wth whch u loutng-pont number muy be
represented n u dgtu computer's memory. 1he 38 dgts eve ol precson ollered by the
dutubuse uows you to store very urge numbers.
1hut precson cupubty s lne when workng wth numbers n the dutubuse, but }uvu uses ts
own set ol types to represent numbers. 1hs meuns you must be curelu when seectng the }uvu
type thut w be used to represent numbers n your progrums, especuy l those numbers ure
gong to be stored n u dutubuse.
1o store ntegers n your }uvu progrum, you cun use the short, int, long, or java.math
.BigInteger types, dependng on how bg the nteger you wunt to store s. 1ube l5-4 shows
the number ol bts used to store short, int, und long types, uong wth the ow und hgh
vuues supported by euch type.
1o store loutng-pont numbers n your }uvu progrums, you cun use the float, double,
or java.math.BigDecimal types. 1ube l5-5 shows the sume coumns us 1ube l5-4 lor the
float und double types, uong wth the precson supported by euch ol these types.
As you cun see, u float muy be used to store loutng-pont numbers wth u precson ol up
to 6 dgts, und u double muy be used lor loutng-pont numbers wth u precson ol up to l5
dgts. ll you huve u loutng-pont number thut requres more thun l5 dgts ol precson lor storuge
n your }uvu progrum, you cun use the java.math.BigDecimal type, whch cun store un
urbtrury ong loutng-pont number.
ln uddton to these types, there s one ol the Cruce }DC extenson types you cun use to
store your ntegers or loutng-pont numbers. 1hs type s oracle.sql.NUMBER, und t uows
you to store numbers wth up to 38 dgts ol precson. You' eurn more ubout the oracle.sql
.NUMBER type uter n ths chupter. ln Cruce Dutubuse l0g und ubove, you cun use the oracle
.sql.BINARY_FLOAT und oracle.sql.BINARY_DOUBLE types. 1hese types uow you to
store the BINARY_FLOAT und BINARY_DOUBLE numbers.
Let's tuke u ook ut some exumpes ol usng these nteger und loutng-pont types to store the
product_id und price coumn vuues lor u row retreved lrom the products tube. Assume
thut u ResultSet obect numed productResultSet hus been popuuted wth the product_
id und price coumns lor u row lrom the products tube. 1he product_id coumn s delned
Typc Bits luw VaIuc High VaIuc
short
l6 32768 32767
int
32 2l47483648 2l47483647
long
64 9223372036854775808 9223372036854775807
TABlf 1S-4 Thc short, int, and long T,pc
SS0
Cruce Dutubuse llg SQL
us u dutubuse INTEGER, und the prce coumn s delned us u dutubuse NUMBER. 1he loowng
exumpe creutes vurubes ol the vurous nteger und loutng-pont types und retreves the
product_id und price coumn vuues nto those vurubes:
short productIdShort = productResultSet.getShort("product_id");
int productIdInt = productResultSet.getInt("product_id");
long productIdLong = productResultSet.getLong("product_id");
float priceFloat = productResultSet.getFloat("price");
double priceDouble = productResultSet.getDouble("price");
java.math.BigDecimal priceBigDec = productResultSet.getBigDecimal("price");
Notce the use ol the dllerent get methods to retreve the coumn vuues us the dllerent
types, the output ol whch s then stored n u }uvu vurube ol the upproprute type.
HandIing Databasc NuII VaIucs
A coumn n u dutubuse tube muy be delned us beng NULL or NOT NULL. NULL ndcutes thut
the coumn muy store u NULL vuue, NOT NULL ndcutes thut the coumn muy not contun u
NULL vuue. A NULL vuue meuns thut the vuue s unknown. \hen u tube s creuted n the
dutubuse und you don't specly thut u coumn s NULL or NOT NULL, the dutubuse ussumes you
meun NULL.
1he }uvu obect types, such us String, muy be used to store dutubuse NULL vuues. \hen u
query s used to retreve u coumn thut contuns u NULL vuue nto u }uvu String, thut String
w contun u }uvu null vuue. lor exumpe, the phone coumn (u VARCHAR2) lor customer r5
s NULL, und the loowng stutement uses the getString() method to reud thut vuue nto u
String numed phone:
phone = customerResultSet.getString("phone");
Cnce the stutement s run, the phone }uvu String w contun the }uvu null vuue.
1hut method's lne lor NULL vuues beng stored n }uvu obects, but whut ubout the }uvu
numerc, ogcu, und bt type types: ll you retreve u NULL vuue nto u }uvu numerc, ogcu, or
bt vurubeint, float, boolean, or byte, lor exumpethut vurube w contun the vuue
zero. 1o the dutubuse, zero und NULL ure dllerent vuues: zero s u delnte vuue, NULL meuns
the vuue s unknown. 1hs cuuses u probem l you wunt to dllerentute between zero und NULL
n your }uvu progrum.
1here ure two wuys to get uround ths probem:
You cun use the wasNull() method n the ResultSet. 1he wasNull() method
returns true l the vuue retreved lrom the dutubuse wus NULL, otherwse, the method
returns false.
Typc Bits luw VaIuc High VaIuc Prccisiun
float
32 3.4L+38 3.4L+38 6 dgts
double
64 l.7L+308 l.7L+308 l5 dgts
TABlf 1S-S Thc float and double T,pc
Chupter l5: Runnng SQL Lsng }uvu

You cun use u }uvu vrappcr ca. A wrupper cuss s u }uvu cuss thut uows you to delne
u vrappcr ob]cc|, whch cun then be used to store the coumn vuue returned lrom the
dutubuse. A wrupper obect stores dutubuse NULL vuues us }uvu null vuues, und non-
NULL vuues ure stored us reguur vuues.
Let's tuke u ook ut un exumpe thut ustrutes the use ol lrst technque, usng product rl2
lrom the products tube. 1hs row hus u NULL vuue n the product_type_id coumn, und
ths coumn s delned us u dutubuse INTEGER. Aso, ussume thut u ResultSet obect numed
productResultSet hus been popuuted wth the product_id und product_type_id
coumns lor product rl2 lrom the products tube. 1he loowng exumpe uses the wasNull()
method to check l the vuue reud lor the product_type_id coumn wus NULL:
System.out.println("product_type_id = " +
productResultSet.getInt("product_type_id"));
if (productResultSet.wasNull()) {
System.out.println("Last value read was NULL");
}
ecuuse the product_type_id coumn contuns u NULL vuue, wasNull() w return
true, und so the strng "Last value read was NULL" woud be dspuyed.
elore you see un exumpe ol the second method thut uses the }uvu wrupper cusses, l need
to expun whut these wrupper cusses uctuuy ure. 1he wrupper cusses ure delned n the java
.lang puckuge, wth the loowng seven wrupper cusses beng delned n thut puckuge:
java.lang.Short
java.lang.Integer
java.lang.Long
java.lang.Float
java.lang.Double
java.lang.Boolean
java.lang.Byte
Cbects decured usng these wrupper cusses cun be used to represent dutubuse NULL vuues
lor the vurous types ol numbers us we us lor the Boolean type. \hen u dutubuse NULL s
retreved nto such un obect, t w contun the }uvu null vuue. 1he loowng exumpe decures
u java.lang.Integer numed productTypeId:
java.lang.Integer productTypeId;
A dutubuse NULL muy then be stored n productTypeId usng u cu to the getObject()
method, us shown n the loowng exumpe:
productTypeId =
(java.lang.Integer) productResultSet.getObject("product_type_id");
1he getObject() method returns un nstunce ol the java.lang.Object cuss und must
be cust nto un upproprute type, n ths cuse, to u java.lang.Integer. Assumng ths exumpe
SS2
Cruce Dutubuse llg SQL
reuds the sume row lrom productResultSet us the prevous exumpe, getObject() w
return u }uvu null vuue, und ths vuue w be coped nto productTypeId. Cl course, l the
vuue retreved lrom the dutubuse hud u vuue other thun NULL, productTypeId woud contun
thut vuue. lor exumpe, l the vuue retreved lrom the dutubuse wus l, productTypeId woud
contun the vuue l.
You cun uso use u wrupper obect n u }DC stutement thut perlorms un INSERT or UPDATE
to set u coumn to u reguur vuue or u NULL vuue. ll you wunt to set u coumn vuue to NULL
usng u wrupper obect, you woud set thut wrupper obect to null und use t n un INSERT or
UPDATE stutement to set the dutubuse coumn to NULL. 1he loowng exumpe sets the price
coumn lor product rl2 to NULL usng u java.lang.Double obect thut s set to null:
java.lang.Double price = null;
myStatement.executeUpdate(
"UPDATE products " +
"SET price = " + price + " " +
"WHERE product_id = 12"
);
CuntruIIing Databasc Transactiuns
ln Chupter 8 you eurned ubout dutubuse trunsuctons und how to use the SQL COMMIT stutement
to permunenty record chunges you muke to the contents ol tubes. You uso suw how to use the
ROLLBACK stutement to undo chunges n u dutubuse trunsucton. 1he sume concepts uppy to
SQL stutements executed usng }DC stutements wthn your }uvu progrums.
y deluut, the resuts ol your INSERT, UPDATE, und DELETE stutements executed usng
}DC ure mmedutey commtted. 1hs s known us au|o-comm| mode. Ceneruy, usng uuto-
commt mode s no| the prelerred wuy ol commttng chunges, becuuse t s counter to the deu
ol consderng trunsuctons us ogcu unts ol work. \th uuto-commt mode, u stutements ure
consdered us ndvduu trunsuctons, und ths ussumpton s usuuy ncorrect. Aso, uuto-commt
mode muy cuuse your SQL stutements to tuke onger to compete, due to the luct thut euch
stutement s uwuys commtted.
lortunutey, you cun enube or dsube uuto-commt mode usng the setAutoCommit()
method ol the Connection cuss, pussng t u ooeun true or false vuue. 1he loowng
exumpe dsubes uuto-commt mode lor the Connection obect numed myConnection:
myConnection.setAutoCommit(false);
TlP
You houd dabc au|o-comm| modc. Dong |h v uua, ma|c
,our program run |a|cr.
Cnce uuto-commt hus been dsubed, you cun commt your trunsucton chunges usng the
commit() method ol the Connection cuss, or you cun ro buck your chunges usng the
rollback() method. ln the loowng exumpe, the commit() method s used to commt
chunges mude to the dutubuse usng the myConnection obect:
myConnection.commit();
ln the next exumpe, the rollback() method s used to ro buck chunges mude to the
dutubuse:
myConnection.rollback();
Chupter l5: Runnng SQL Lsng }uvu
SS3
ll uuto-commt hus been dsubed und you cose your Connection obect, un mpct
commt s perlormed. 1herelore, uny DML stutements you huve perlormed up to thut pont und
huven't ureudy commtted w be commtted uutomutcuy.
Pcrfurming Data Dcfinitiun languagc Statcmcnts
1he SQL Dutu Delnton Lunguuge (DDL) stutements ure used to creute dutubuse users, tubes,
und muny other types ol dutubuse structures thut muke up u dutubuse. DDL conssts ol stutements
such us CREATE, ALTER, DROP, TRUNCATE, und RENAME. DDL stutements muy be perlormed
n }DC usng the execute() method ol the Statement cuss. ln the loowng exumpe, the
CREATE TABLE stutement s used to creute u tube numed addresses, whch muy be used to
store customer uddresses:
myStatement.execute(
"CREATE TABLE addresses (" +
" address_id INTEGER CONSTRAINT addresses_pk PRIMARY KEY," +
" customer_id INTEGER CONSTRAINT addresses_fk_customers " +
" REFERENCES customers(customer_id)," +
" street VARCHAR2(20) NOT NULL," +
" city VARCHAR2(20) NOT NULL," +
" state CHAR(2) NOT NULL" +
")"
);
NOTf
cr|ormng a DD |a|cmcn| rcu| n an mpc| comm| bcng
ucd. Thcrc|orc, | ,ou'vc pcr|ormcd uncomm||cd D\ |a|cmcn|
pror |o ung a DD |a|cmcn|, |hoc D\ |a|cmcn| v ao bc
comm||cd.
HandIing fxccptiuns
\hen un error occurs n ether the dutubuse or the }DC drver, u java.sql.SQLException
w be rused. 1he java.sql.SQLException cuss s u subcuss ol the java.lang.Exception
cuss. lor ths reuson, you must puce u your }DC stutements wthn u try/catch stutement n
order lor your code not to throw u java.sql.SQLException. \hen such un excepton occurs,
}uvu uttempts to ocute the upproprute hunder to process the excepton.
ll you ncude u hunder lor u java.sql.SQLException n u catch cuuse, when un error
occurs n ether the dutubuse or the }DC drver, }uvu w move to thut hunder und run the
upproprute code thut you've ncuded n thut catch cuuse. ln the hunder code, you cun do
thngs ke dspuy the error code und error messuge, whch w hep you determne whut huppened.
1he loowng try/catch stutement contuns u hunder lor exceptons ol type java.sql
.SQLException thut muy occur n the try stutement:
try {
...
} catch (SQLException e) {
...
}
SS4
Cruce Dutubuse llg SQL
NOTf
'm aumng java.sql.* ha bccn mpor|cd, o can mp, uc
SQLException n |hc ca|ch, ra|hcr |han havng |o rc|crcncc java
.sql.SQLException.
1he try stutement w contun your }DC stutements thut muy cuuse un SQLException to
be thrown, und the catch cuuse w contun your error hundng code.
1he SQLException cuss delnes lour methods thut ure uselu lor lndng out whut cuused
the excepton to occur:
getErrorCode() ln the cuse ol errors thut occur n the dutubuse or the }DC drver,
ths method returns the Cruce error code, whch s u lve-dgt number.
getMessage() ln the cuse ol errors thut occur n the dutubuse, ths method returns the
error messuge uong wth the lve-dgt Cruce error code. ln the cuse ol errors thut occur
n the }DC drver, ths method returns ust the error messuge.
getSQLState() ln the cuse ol errors thut occur n the dutubuse, ths method returns
u lve-dgt code contunng the SQL stute. ln the cuse ol errors thut occur n the }DC
drver, ths method doesn't return unythng ol nterest.
printStackTrace() 1hs method dspuys the contents ol the stuck when the
excepton occurred. 1hs nlormuton muy lurther ussst you n lndng out whut went wrong.
1he loowng try/catch stutement ustrutes the use ol these lour methods:
try {
...
} catch (SQLException e) {
System.out.println("Error code = " + e.getErrorCode());
System.out.println("Error message = " + e.getMessage());
System.out.println("SQL state = " + e.getSQLState());
e.printStackTrace();
}
ll your code throws un SQLException ruther thun hundng t ocuy us ust shown, }uvu w
seurch lor un upproprute hunder n the cung procedure or luncton unt one s lound. ll none
s lound, the excepton w be hunded by the deluut excepton hunder, whch dspuys the
Cruce error code, the error messuge, und the stuck truce.
CIusing Yuur |DBC Objccts
ln the exumpes shown n ths chupter, l've creuted u number ol }DC obects: u Connection
obect numed myConnection, u Statement obect numed myStatement, und two
ResultSet obects numed customerResultSet und productResultSet. ResultSet
obects shoud be cosed when they ure no onger needed usng the close() method. Smury,
you shoud uso cose the Statement und Connection obects when those obects ure no
onger needed.
ln the loowng exumpe, the myStatement und myConnection obects ure cosed usng
the close() method:
Chupter l5: Runnng SQL Lsng }uvu

myStatement.close();
myConnection.close();
You shoud typcuy cose your Statement und Connection obects n u finally cuuse.
Any code contuned n u finally cuuse s guurunteed to be run, no mutter how contro euves
the try stutement. ll you wunt to udd u finally cuuse to cose your Statement und
Connection obects, those obects shoud be decured belore the lrst try/catch stutement
used to trup exceptons. 1he loowng exumpe shows how to structure the main() method
so thut the Statement und Connection obects muy be cosed n u finally cuuse:
public static void main (String args []) {
// declare Connection and Statement objects
Connection myConnection = null;
Statement myStatement = null;
try {
// register the Oracle JDBC drivers
DriverManager.registerDriver(
new oracle.jdbc.driver.OracleDriver()
);
// connect to the database as store
// using the Oracle JDBC Thin driver
myConnection = DriverManager.getConnection(
"jdbc:oracle:thin:@localhost:1521:ORCL",
"store",
"store_password"
);
// create a Statement object
myStatement = myConnection.createStatement();
// more of your code goes here
...
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
// close the Statement object using the close() method
if (myStatement != null) {
myStatement.close();
}
// close the Connection object using the close() method
if (myConnection != null) {
myConnection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
} // end of main()
SS6
Cruce Dutubuse ll SQL
Notce thut the code n the finally cuuse checks to see l the Statement und Connection
obects ure not equu to null belore cosng them usng the close() method. ll they ure equu
to null, there s no need to cose them. ecuuse the code n the finally cuuse s the ust thng
to be run und s guurunteed to be run, the Statement und Connection obects ure uwuys
cosed, regurdess ol whut ese huppens n your progrum. lor the suke ol brevty, ony the
lrst progrum leutured n ths chupter uses u finally cuuse to cose the Statement und
Connection obects.
You huve now seen how to wrte }DC stutements thut connect to u dutubuse, run DML und
DDL stutements, contro trunsuctons, hunde exceptons, und cose }DC obects. 1he loowng
secton contuns u compete progrum thut ustrutes the use ol }DC.
fxampIc Prugram: BasicfxampIc1.java
1he BasicExample1.java progrum ustrutes the concepts covered n ths chupter so lur. 1hs
progrum und the other progrums leutured n ths chupter muy be lound n the Java loder where you
extructed ths book's Zp le. A the progrums contun detued comments thut you shoud study.
/*
BasicExample1.java shows how to:
- import the JDBC packages
- load the Oracle JDBC drivers
- connect to a database
- perform DML statements
- control transactions
- use ResultSet objects to retrieve rows
- use the get methods
- perform DDL statements
*/
// import the JDBC packages
import java.sql.*;
public class BasicExample1 {
public static void main (String args []) {
// declare Connection and Statement objects
Connection myConnection = null;
Statement myStatement = null;
try {
// register the Oracle JDBC drivers
DriverManager.registerDriver(
new oracle.jdbc.OracleDriver()
);
// EDIT AS NECESSARY TO CONNECT TO YOUR DATABASE
// create a Connection object, and connect to the database
// as the store user using the Oracle JDBC Thin driver
myConnection = DriverManager.getConnection(
"jdbc:oracle:thin:@localhost:1521:ORCL",
"store",
Chupter l5: Runnng SQL Lsng }uvu

"store_password"
);
// disable auto-commit mode
myConnection.setAutoCommit(false);
// create a Statement object
myStatement = myConnection.createStatement();
// create variables and objects used to represent
// column values
int customerId = 6;
String firstName = "Jason";
String lastName = "Red";
java.sql.Date dob = java.sql.Date.valueOf("1969-02-22");
java.sql.Time dobTime;
java.sql.Timestamp dobTimestamp;
String phone = "800-555-1216";
// perform SQL INSERT statement to add a new row to the
// customers table using the values set in the previous
// step - the executeUpdate() method of the Statement
// object is used to perform the INSERT
myStatement.executeUpdate(
"INSERT INTO customers " +
"(customer_id, first_name, last_name, dob, phone) VALUES (" +
customerId + ", '" + firstName + "', '" + lastName + "', " +
"TO_DATE('" + dob + "', 'YYYY, MM, DD'), '" + phone + "')"
);
System.out.println("Added row to customers table");
// perform SQL UPDATE statement to modify the first_name
// column of customer #1
firstName = "Jean";
myStatement.executeUpdate(
"UPDATE customers " +
"SET first_name = '" + firstName + "' " +
"WHERE customer_id = 1"
);
System.out.println("Updated row in customers table");
// perform SQL DELETE statement to remove customer #5
myStatement.executeUpdate(
"DELETE FROM customers " +
"WHERE customer_id = 5"
);
System.out.println("Deleted row from customers table");
// create a ResultSet object, and populate it with the
// result of a SELECT statement that retrieves the
// customer_id, first_name, last_name, dob, and phone columns

Cruce Dutubuse ll SQL
// for all the rows from the customers table - the
// executeQuery() method of the Statement object is used
// to perform the SELECT
ResultSet customerResultSet = myStatement.executeQuery(
"SELECT customer_id, first_name, last_name, dob, phone " +
"FROM customers"
);
System.out.println("Retrieved rows from customers table");
// loop through the rows in the ResultSet object using the
// next() method, and use the get methods to read the values
// retrieved from the database columns
while (customerResultSet.next()) {
customerId = customerResultSet.getInt("customer_id");
firstName = customerResultSet.getString("first_name");
lastName = customerResultSet.getString("last_name");
dob = customerResultSet.getDate("dob");
dobTime = customerResultSet.getTime("dob");
dobTimestamp = customerResultSet.getTimestamp("dob");
phone = customerResultSet.getString("phone");
System.out.println("customerId = " + customerId);
System.out.println("firstName = " + firstName);
System.out.println("lastName = " + lastName);
System.out.println("dob = " + dob);
System.out.println("dobTime = " + dobTime);
System.out.println("dobTimestamp = " + dobTimestamp);
System.out.println("phone = " + phone);
} // end of while loop
// close the ResultSet object using the close() method
customerResultSet.close();
// roll back the changes made to the database
myConnection.rollback();
// create numeric variables to store the product_id and price columns
short productIdShort;
int productIdInt;
long productIdLong;
float priceFloat;
double priceDouble;
java.math.BigDecimal priceBigDec;
// create another ResultSet object and retrieve the
// product_id, product_type_id, and price columns for product #12
// (this row has a NULL value in the product_type_id column)
ResultSet productResultSet = myStatement.executeQuery(
"SELECT product_id, product_type_id, price " +
"FROM products " +
"WHERE product_id = 12"
);
Chupter l5: Runnng SQL Lsng }uvu

System.out.println("Retrieved row from products table");


while (productResultSet.next()) {
System.out.println("product_id = " +
productResultSet.getInt("product_id"));
System.out.println("product_type_id = " +
productResultSet.getInt("product_type_id"));
// check if the value just read by the get method was NULL
if (productResultSet.wasNull()) {
System.out.println("Last value read was NULL");
}
// use the getObject() method to read the value, and convert it
// to a wrapper object - this converts a database NULL value to a
// Java null value
java.lang.Integer productTypeId =
(java.lang.Integer) productResultSet.getObject("product_type_id");
System.out.println("productTypeId = " + productTypeId);
// retrieve the product_id and price column values into
// the various numeric variables created earlier
productIdShort = productResultSet.getShort("product_id");
productIdInt = productResultSet.getInt("product_id");
productIdLong = productResultSet.getLong("product_id");
priceFloat = productResultSet.getFloat("price");
priceDouble = productResultSet.getDouble("price");
priceBigDec = productResultSet.getBigDecimal("price");
System.out.println("productIdShort = " + productIdShort);
System.out.println("productIdInt = " + productIdInt);
System.out.println("productIdLong = " + productIdLong);
System.out.println("priceFloat = " + priceFloat);
System.out.println("priceDouble = " + priceDouble);
System.out.println("priceBigDec = " + priceBigDec);
} // end of while loop
// close the ResultSet object
productResultSet.close();
// perform SQL DDL CREATE TABLE statement to create a new table
// that may be used to store customer addresses
myStatement.execute(
"CREATE TABLE addresses (" +
" address_id INTEGER CONSTRAINT addresses_pk PRIMARY KEY," +
" customer_id INTEGER CONSTRAINT addresses_fk_customers " +
" REFERENCES customers(customer_id)," +
" street VARCHAR2(20) NOT NULL," +
" city VARCHAR2(20) NOT NULL," +
" state CHAR(2) NOT NULL" +
")"
);
System.out.println("Created addresses table");
S60
Cruce Dutubuse llg SQL
// drop this table using the SQL DDL DROP TABLE statement
myStatement.execute("DROP TABLE addresses");
System.out.println("Dropped addresses table");
} catch (SQLException e) {
System.out.println("Error code = " + e.getErrorCode());
System.out.println("Error message = " + e.getMessage());
System.out.println("SQL state = " + e.getSQLState());
e.printStackTrace();
} finally {
try {
// close the Statement object using the close() method
if (myStatement != null) {
myStatement.close();
}
// close the Connection object using the close() method
if (myConnection != null) {
myConnection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
} // end of main()
}
NOTf
You ma, nccd |o cd| |hc nc abccd v|h |hc |cx| EDIT AS
NECESSARY... v|h |hc corrcc| c||ng |o accc ,our da|abac.
CumpiIc BasicfxampIc1
1o compe BasicExample1.java, you type the loowng commund usng your operutng
system commund prompt:
javac BasicExample1.java
ll you huven't set the CLASSPATH envronment vurube propery, you' get the loowng
error messuge when tryng to compe the FirstExample.java progrum:
FirstExample.java:22: cannot resolve symbol
symbol : class OracleDriver
location: package jdbc
new oracle.jdbc.OracleDriver()
^
1 error
You shoud check the settng lor your CLASSPATH envronment vurubet's key your
CLASSPATH s mssng the Cruce }DC cusses le (ojdbc6.jar, lor exumpe). Reler to the
eurer secton Settng the CLASSlA1H Lnvronment Vurube.
TlP
You can cn|cr javac -help |o gc| hcp on |hc }ava compcr.
Chupter l5: Runnng SQL Lsng }uvu
S61
Run BasicfxampIc1
Cnce BasicExample1.java s comped, you cun run the resutng executube cuss le
(numed BasicExample1.class) by enterng the loowng commund:
java BasicExample1
CAUTlON
}ava cac-cn|vc, o ma|c urc ,ou cn|cr BasicExample1 v|h
uppcrcac and charac|cr.
ll the progrum lus wth the loowng error code und messuge, t meuns the store user wth
u pussword ol store_password doesn't exst n your dutubuse:
Error code = 1017
Error message = ORA-01017: invalid username/password; logon denied
ll you get ths error, check thut the store user s n the dutubuse.
1he progrum muy uso be unube to lnd your dutubuse, n whch cuse you' get the loowng
error:
Error code = 17002
Error message = Io exception: The Network Adapter could not establish
the connection
1ypcuy, there ure two reusons why you mght get ths error:
1here s no dutubuse runnng on your localhost muchne wth the Cruce SlD ol ORCL.
Cruce Net s not runnng or s not stenng lor connectons on port l52l.
You shoud ensure thut you huve the rght connecton strng n the progrum und uso thut the
dutubuse und Cruce Net ure runnng.
Assumng the progrum runs, you shoud get the loowng output:
Added row to customers table
Updated row in customers table
Deleted row from customers table
Retrieved rows from customers table
customerId = 1
firstName = Jean
lastName = Brown
dob = 1965-01-01
dobTime = 00:00:00
dobTimestamp = 1965-01-01 00:00:00.0
phone = 800-555-1211
customerId = 2
firstName = Cynthia
lastName = Green
dob = 1968-02-05
dobTime = 00:00:00
dobTimestamp = 1968-02-05 00:00:00.0
phone = 800-555-1212
S62
Cruce Dutubuse llg SQL
customerId = 3
firstName = Steve
lastName = White
dob = 1971-03-16
dobTime = 00:00:00
dobTimestamp = 1971-03-16 00:00:00.0
phone = 800-555-1213
customerId = 4
firstName = Gail
lastName = Black
dob = null
dobTime = null
dobTimestamp = null
phone = 800-555-1214
customerId = 6
firstName = Jason
lastName = Red
dob = 1969-02-22
dobTime = 00:00:00
dobTimestamp = 1969-02-22 00:00:00.0
phone = 800-555-1216
Retrieved row from products table
product_id = 12
product_type_id = 0
Last value read was NULL
productTypeId = null
productIdShort = 12
productIdInt = 12
productIdLong = 12
priceFloat = 13.49
priceDouble = 13.49
priceBigDec = 13.49
Created addresses table
Dropped addresses table
Prcparcd SQl Statcmcnts
\hen you send un SQL stutement to the dutubuse, the dutubuse soltwure reuds the SQL stutement
und verles thut t s correct. 1hs s known us parng the SQL stutement. 1he dutubuse soltwure
then buds u pun, known us the cxccu|on pan, to uctuuy run the stutement. So lur, u the SQL
stutements sent to the dutubuse through }DC huve requred u new executon pun to be but.
1hs s becuuse euch SQL stutement sent to the dutubuse hus been dllerent.
Suppose you hud u }uvu uppcuton thut wus perlormng the sume INSERT stutement repeutedy,
un exumpe s oudng muny new products to our exumpe store, u process thut woud requre
uddng ots ol rows to the products tube usng INSERT stutements. Let's see }uvu stutements
thut woud uctuuy do ths. Assume thut u cuss numed Product hus been delned us loows:
class Product {
int productId;
int productTypeId;
String name;
Chupter l5: Runnng SQL Lsng }uvu

String description;
double price;
}
1he loowng code creutes un urruy ol lve Product obects. ecuuse the products tube
ureudy contuns rows wth product_id vuues lrom l to l2, the productId uttrbutes lor the
new Product obects sturt ut l3:
Product [] productArray = new Product[5];
for (int counter = 0; counter < productArray.length; counter ++) {
productArray[counter] = new Product();
productArray[counter].productId = counter + 13; //start at 13
productArray[counter].productTypeId = 1;
productArray[counter].name = "Test product";
productArray[counter].description = "Test product";
productArray[counter].price = 19.95;
} // end of for loop
1o udd the rows to the products tube, l' use u for oop thut contuns u }DC stutement to
perlorm un INSERT stutement, und the coumn vuues w come lrom productArray:
Statement myStatement = myConnection.createStatement();
for (int counter = 0; counter < productArray.length; counter ++) {
myStatement.executeUpdate(
"INSERT INTO products " +
"(product_id, product_type_id, name, description, price) VALUES (" +
productArray[counter]. productId + ", " +
productArray[counter]. productTypeId + ", '" +
productArray[counter].name + "', '" +
productArray[counter].description + "', " +
productArray[counter].price + ")"
);
} // end of for loop
Luch teruton through the oop resuts n un INSERT stutement beng sent to the dutubuse.
ecuuse the strng representng euch INSERT stutement contuns dllerent vuues, the uctuu
INSERT sent to the dutubuse s sghty dllerent euch tme. 1hs meuns thut the dutubuse creutes
u dllerent executon pun lor every INSERT stutementvery nellcent.
You' be gud to know thut }DC provdes u better wuy to run such SQL stutements.
lnsteud ol usng u }DC Statement obect to run your SQL stutements, you cun use u }DC
PreparedStatement obect. A PreparedStatement obect uows you to perlorm the sume
SQL stutement but suppy dllerent vuues lor uctuu executon ol thut stutement. 1hs s more
ellcent becuuse the sume executon pun s used by the dutubuse when the SQL stutement s run.
1he loowng exumpe creutes u PreparedStatement obect contunng un INSERT stutement
smur to the one used n the prevous oop:
PreparedStatement myPrepStatement = myConnection.prepareStatement(
"INSERT INTO products " +
"(product_id, product_type_id, name, description, price) VALUES (" +
"?, ?, ?, ?, ?"
")"
);

Cruce Dutubuse llg SQL
1here ure two thngs you shoud notce ubout ths exumpe:
1he prepareStatement() method s used to specly the SQL stutement.
Queston murk churucters (:) ure used to ndcute the postons where you w uter
provde vurubes to be used when the SQL stutement s uctuuy run.
1he postons ol the queston murks ure mportunt: they ure relerenced uccordng to ther
poston, wth the lrst queston murk beng relerenced usng number l, the second us number 2,
und so on.
1he process ol suppyng }uvu vurubes to u prepured stutement s known us bndng the
vurubes to the stutement, und the vurubes themseves ure known us bnd varabc. 1o uctuuy
suppy vurubes to the prepured SQL stutement, you must use set methods. 1hese methods ure
smur to the get methods dscussed eurer, except thut set methods ure used to suppy vurube
vuues, ruther thun reud them.
lor exumpe, to bnd u }uvu int vurube numed intVar to the product_id coumn
n the PreparedStatement obect, you use setInt(1, intVar). 1he lrst purumeter
ndcutes the numerc poston ol the queston murk (:) n the strng prevousy specled n the
prepareStatement() method cu. lor ths exumpe, the vuue l corresponds to the lrst
queston murk, whch suppes u vuue to the product_id coumn n the INSERT stutement.
Smury, to bnd u }uvu String vurube numed stringVar to the name coumn, you use
setString(3, stringVar), becuuse the thrd queston murk corresponds to the name
coumn. Cther methods you cun cu n u PreparedStatement obect ncude setFloat()
und setDouble(), whch ure used lor settng snge-precson loutng-pont und doube-
precson loutng-pont numbers.
1he loowng exumpe leutures u oop thut shows the use ol set methods to bnd the
uttrbutes ol the Product obects n productArray to the PreparedStatement obect,
notce the execute() method s used to uctuuy run the SQL stutement:
for (int counter = 0; counter < productArray.length; counter ++) {
myPrepStatement.setInt(1, productArray[counter]. productId);
myPrepStatement.setInt(2, productArray[counter]. productTypeId);
myPrepStatement.setString(3, productArray[counter].name);
myPrepStatement.setString(4, productArray[counter].description);
myPrepStatement.setDouble(5, productArray[counter].price);
myPrepStatement.execute();
} // end of for loop
Alter ths code s executed, the products tube w contun lve new rows.
1o set u dutubuse coumn to NULL usng u PreparedStatement obect, you muy use the
setNull() method. lor exumpe, the loowng stutement sets the description coumn
to NULL:
myPrepStatement.setNull(4, java.sql.Types.VARCHAR);
1he lrst purumeter n the cu to setNull() s the numerc poston ol the coumn you wunt to
set to NULL. 1he second purumeter s un int thut corresponds to the dutubuse type ol the coumn
thut s to be set to NULL. 1hs second purumeter shoud be specled usng one ol the constunts
delned n the java.sql.Types cuss. lor u VARCHAR2 coumn (the description coumn s
u VARCHAR2), you shoud use java.sql.Types.VARCHAR.
Chupter l5: Runnng SQL Lsng }uvu
S6S
fxampIc Prugram: BasicfxampIc2.java
1he loowng BasicExample2.java progrum contuns the stutements shown n the prevous
sectons.
/*
BasicExample2.java shows how to use prepared SQL statements
*/
// import the JDBC packages
import java.sql.*;
class Product {
int productId;
int productTypeId;
String name;
String description;
double price;
}
public class BasicExample2 {
public static void main (String args []) {
try {
// register the Oracle JDBC drivers
DriverManager.registerDriver(
new oracle.jdbc.OracleDriver()
);
// EDIT AS NECESSARY TO CONNECT TO YOUR DATABASE
// create a Connection object, and connect to the database
// as the store user using the Oracle JDBC Thin driver
Connection myConnection = DriverManager.getConnection(
"jdbc:oracle:thin:@localhost:1521:ORCL",
"store",
"store_password"
);
// disable auto-commit mode
myConnection.setAutoCommit(false);
Product [] productArray = new Product[5];
for (int counter = 0; counter < productArray.length; counter ++) {
productArray[counter] = new Product();
productArray[counter].productId = counter + 13;
productArray[counter].productTypeId = 1;
productArray[counter].name = "Test product";
productArray[counter].description = "Test product";
productArray[counter].price = 19.95;
} // end of for loop
// create a PreparedStatement object

Cruce Dutubuse ll SQL
PreparedStatement myPrepStatement = myConnection.prepareStatement(
"INSERT INTO products " +
"(product_id, product_type_id, name, description, price) VALUES (" +
"?, ?, ?, ?, ?" +
")"
);
// initialize the values for the new rows using the
// appropriate set methods
for (int counter = 0; counter < productArray.length; counter ++) {
myPrepStatement.setInt(1, productArray[counter].productId);
myPrepStatement.setInt(2, productArray[counter].productTypeId);
myPrepStatement.setString(3, productArray[counter].name);
myPrepStatement.setString(4, productArray[counter].description);
myPrepStatement.setDouble(5, productArray[counter].price);
myPrepStatement.execute();
} // end of for loop
// close the PreparedStatement object
myPrepStatement.close();
// retrieve the product_id, product_type_id, name, description, and
// price columns for these new rows using a ResultSet object
Statement myStatement = myConnection.createStatement();
ResultSet productResultSet = myStatement.executeQuery(
"SELECT product_id, product_type_id, " +
" name, description, price " +
"FROM products " +
"WHERE product_id > 12"
);
// display the column values
while (productResultSet.next()) {
System.out.println("product_id = " +
productResultSet.getInt("product_id"));
System.out.println("product_type_id = " +
productResultSet.getInt("product_type_id"));
System.out.println("name = " +
productResultSet.getString("name"));
System.out.println("description = " +
productResultSet.getString("description"));
System.out.println("price = " +
productResultSet.getDouble("price"));
} // end of while loop
// close the ResultSet object using the close() method
productResultSet.close();
// roll back the changes made to the database
myConnection.rollback();
// close the other JDBC objects
Chupter l5: Runnng SQL Lsng }uvu
S67
myStatement.close();
myConnection.close();
} catch (SQLException e) {
System.out.println("Error code = " + e.getErrorCode());
System.out.println("Error message = " + e.getMessage());
System.out.println("SQL state = " + e.getSQLState());
e.printStackTrace();
}
} // end of main()
}
1he output lrom ths progrum s us loows:
product_id = 13
product_type_id = 1
name = Test product
description = Test product
price = 19.95
product_id = 14
product_type_id = 1
name = Test product
description = Test product
price = 19.95
product_id = 15
product_type_id = 1
name = Test product
description = Test product
price = 19.95
product_id = 16
product_type_id = 1
name = Test product
description = Test product
price = 19.95
product_id = 17
product_type_id = 1
name = Test product
description = Test product
price = 19.95
Thc OracIc |DBC fxtcnsiuns
1he Cruce extensons to }DC enube you to uccess u ol the dutu types provded by Cruce,
uong wth Cruce-speclc perlormunce extensons. You' eurn ubout hundng ol strngs,
numbers, dutes, und row dentlers n ths secton. You muy reud my book Cracc9 }DC
rogrammng lor u ol the Cruce types und perlormunce enhuncements.
1here ure two }DC extenson puckuges supped by Cruce Corporuton:
oracle.sql contuns the cusses thut support u the Cruce dutubuse types.
oracle.jdbc contuns the nterluces thut support uccess to un Cruce dutubuse.
S68
Cruce Dutubuse llg SQL
1o mport the Cruce }DC puckuges nto your }uvu progrums, you udd the loowng import
stutements to your progrum:
import oracle.sql.*;
import oracle.jdbc.*;
Cl course, you don't huve to mport u the puckugesyou coud ust mport the cusses und
nterluces you uctuuy use n your progrum. ln the loowng sectons, you' eurn the key leutures
ol the oracle.sql und oracle.jdbc puckuges.
Thc uracIc.sqI Packagc
1he oracle.sql puckuge contuns the cusses thut support u ol the Cruce dutubuse types.
Lsng obects ol the cusses delned n ths puckuge to store dutubuse vuues s more ellcent thun
usng reguur }uvu obects. 1hs s becuuse the dutubuse vuues don't need to be converted to un
upproprute buse }uvu type lrst. Aso, usng u }uvu float or double to represent u loutng-pont
number muy resut n u oss ol precson lor thut number. ll you use un oracle.sql.NUMBER
obect, your numbers never ose precson.
TlP
| ,ou arc vr|ng a program |ha| movc a o| o| da|a around n |hc
da|abac, ,ou houd uc |hc oracle.sql.* cac.
1he oracle.sql cusses extend the oracle.sql.Datum cuss, whch contuns the
lunctonuty thut s common to u the cusses. 1ube l5-6 shows u subset ol the oracle.sql
cusses, uong wth the muppng to the computbe Cruce dutubuse types.
lrom 1ube l5-6, you cun see thut un oracle.sql.NUMBER obect s computbe wth u
dutubuse INTEGER or NUMBER type. An oracle.sql.CHAR obect s computbe wth u dutubuse
CHAR, VARCHAR2, NCHAR, und NVARCHAR2 (NCHAR und NVARCHAR2 ure typcuy used to store
non-Lngsh churucters).
CIass CumpatibIc Databasc Typc
oracle.sql.NUMBER INTEGER
NUMBER
oracle.sql.CHAR CHAR
VARCHAR2
NCHAR
NVARCHAR2
oracle.sql.DATE DATE
oracle.sql.BINARY_FLOAT BINARY_FLOAT
oracle.sql.BINARY_DOUBLE BINARY_DOUBLE
oracle.sql.ROWID ROWID
TABlf 1S-6 Cac and Compa|bc Cracc Da|abac T,pc
Chupter l5: Runnng SQL Lsng }uvu
S69
Cbects decured usng the oracle.sql cusses store dutu us byte urruysuso known
us S |orma|und don't relormut the dutu retreved lrom the dutubuse. 1hs meuns thut no
nlormuton s ost when convertng between un SQL lormut obect und u vuue stored n the
dutubuse.
Luch oracle.sql obect hus u getBytes() method thut returns the bnury dutu stored n
the obect. Luch obect uso hus u toJdbc() method thut returns the bnury dutu us u computbe
}uvu type (un excepton to ths s the oracle.sql.ROWID, where toJdbc() uwuys returns un
oracle.sql.ROWID).
Luch oracle.sql cuss uso provdes methods to convert ther SQL lormut bnury dutu to u
core }uvu type. lor exumpe, stringValue() returns the vuue us }uvu String, intValue()
returns u }uvu int, floatValue() returns u float, doubleValue() returns u double,
bigDecimalValue() returns u java.math.BigDecimal, dateValue() returns u java
.sql.Date, und so on. You use these methods when you wunt to store the SQL lormut dutu n u
core }uvu type or to dspuy the SQL dutu on the screen. Luch oracle.sql cuss uso contuns u
constructor thut uccepts u }uvu vurube, obect, or byte urruy us nput.
As you w see uter, the oracle.jdbc.OraclePreparedStatement cuss contuns u
number ol set methods thut you use to specly vuues lor oracle.sql obects. 1he
OracleResultSet cuss delnes u number ol get methods thut you use to reud vuues lrom
oracle.sql obects.
1he loowng sectons descrbe the mun oracle.sql cusses.
Thc uracIc.sqI.NUMBfR CIass
1he oracle.sql.NUMBER cuss s computbe wth the dutubuse INTEGER und NUMBER types.
1he oracle.sql.NUMBER cuss muy be used to represent u number wth up to 38 dgts ol
precson. 1he loowng exumpe creutes un oracle.sql.NUMBER obect numed customerId,
whch s set to the vuue 6 usng the constructor:
oracle.sql.NUMBER customerId = new oracle.sql.NUMBER(6);
You cun reud the vuue stored n customerId usng the intValue() method, whch
returns the vuue us u }uvu int. lor exumpe:
int customerIdInt = customerId.intValue();
You cun uso set un oracle.sql.NUMBER obect to u loutng-pont number. 1he next
exumpe pusses the vuue l9.95 to the constructor ol un obect numed price:
oracle.sql.NUMBER price = new oracle.sql.NUMBER(19.95);
You cun reud the loutng-pont number stored n price usng the floatValue(),
doubleValue(), und bigDecimalValue() methods, whch return u }uvu float, double,
und bigDecimal respectvey. You cun uso get u loutng-pont number truncuted to un int
usng intValue() (lor exumpe, l9.95 woud be returned us l9). 1he loowng exumpes show
the use ol these methods:
float priceFloat = price.floatValue();
double priceDouble = price.doubleValue();
java.math.BigDecimal priceBigDec = price.bigDecimalValue();
int priceInt = price.intValue();
S70
Cruce Dutubuse llg SQL
1he stringValue() method returns the vuue us u }uvu String:
String priceString = price.stringValue();
Thc uracIc.sqI.CHAR CIass
1he oracle.sql.CHAR cuss s computbe wth the dutubuse CHAR, VARCHAR2, NCHAR,
und NVARCHAR2 types. oth the Cruce dutubuse und the oracle.sql.CHAR cuss contun
gobuzuton support lor muny dllerent unguuges. lor lu detus ol the vurous unguuges
supported by Cruce, see the Cracc Da|abac Coba2a|on Suppor| Cudc pubshed by Cruce
Corporuton.
\hen you retreve churucter dutu lrom the dutubuse nto un oracle.sql.CHAR obect, the
Cruce }DC drver returns thut obect usng ether the dutubuse churucter set (the deluut), the
\L8lSC8859ll churucter set (lSC 8859-l \est Luropeun), or the L1l8 churucter set (Lncode
3.0 L1l-8 Lnversu).
\hen pussng un oracle.sql.CHAR obect to the dutubuse, there ure restrctons on the
churucter set lor the obect. 1he churucter set depends on the dutubuse coumn type thut the
obect w be stored n. ll you ure storng the oracle.sql.CHAR obect n u CHAR or VARCHAR2
coumn, you must use LS7ASCll (ASCll 7-bt Amercun), \L8lSC8859ll (lSC 8859-l \est
Luropeun), or L1l8 (Lncode 3.0 L1l-8 Lnversu). ll you ure storng the oracle.sql.CHAR
obect n un NCHAR or NVARCHAR2 coumn, you must use the churucter set used by the dutubuse.
\hen creutng your own oracle.sql.CHAR obect, there ure two steps you must loow:
1. Creute un oracle.sql.CharacterSet obect wth the churucter set you wsh to use.
2. Creute un oracle.sql.CHAR obect through the oracle.sql.CharacterSet obect.
1he loowng sectons cover these steps.
5tep 1: Create an orac|e.sq|.Character5et 0bject 1he loowng exumpe creutes un oracle
.sql.CharacterSet obect numed myCharSet:
oracle.sql.CharacterSet myCharSet =
CharacterSet.make(CharacterSet.US7ASCII_CHARSET);
1he make() method uccepts un int thut specles the churucter set. ln the exumpe, the
constunt US7ASCII_CHARSET (delned n the oracle.sql.CharacterSet cuss) specles
the LS7ASCll churucter set. Cther int vuues ncude UTF8_CHARSET (lor L1l8) und
DEFAULT_CHARSET (lor the churucter set used by the dutubuse).
5tep 2: Create an orac|e.sq|.Chkk 0bject 1he next exumpe creutes un oracle.sql.CHAR
obect numed firstName, usng the myCharSet obect creuted n the prevous step:
oracle.sql.CHAR firstName = new oracle.sql.CHAR("Jason", myCharSet);
1he firstName obect s popuuted wth the strng Jason. You cun reud ths strng usng the
stringValue() method, lor exumpe:
String firstNameString = firstName.stringValue();
System.out.println("firstNameString = " + firstNameString);
Chupter l5: Runnng SQL Lsng }uvu
S71
1hs w dspuy firstNameString = Jason.
Smury, the loowng exumpe creutes unother oracle.sql.CHAR obect numed lastName:
oracle.sql.CHAR lastName = new oracle.sql.CHAR("Price", myCharSet);
You cun uso dspuy the vuue n un oracle.sql.CHAR obect drecty, us shown n the
loowng exumpe:
System.out.println("lastName = " + lastName);
1hs stutement dspuys the loowng:
lastName = Price
Thc uracIc.sqI.DATf CIass
1he oracle.sql.DATE cuss s computbe wth the dutubuse DATE type. 1he loowng
exumpe creutes un oracle.sql.DATE obect numed dob:
oracle.sql.DATE dob = new oracle.sql.DATE("1969-02-22 13:54:12");
Notce thut the constructor muy uccept u strng n the lormut YYYY-MM-DD HH:MI:SS, where
YYYY s the yeur, MM s the month, DD s the duy, HH s the hour, MI s the mnute, und SS s the
second. You cun reud the vuue stored n dob us u }uvu String usng the stringValue()
method, us shown n the loowng exumpe:
String dobString = dob.stringValue();
ln ths exumpe, dobString w contun 2/22/1969 13:54:12 (the lormut chunges to
MM/DD/YYYY HH:MI:SS when usng u }uvu String).
You cun uso puss u java.sql.Date obect to the oracle.sql.DATE constructor, us
shown n the loowng exumpe:
oracle.sql.DATE anotherDob =
new oracle.sql.DATE(java.sql.Date.valueOf("1969-02-22"));
ln ths exumpe, anotherDob w contun the oracle.sql.DATE 1969-02-22
00:00:00.
Thc uracIc.sqI.ROWlD CIass
1he oracle.sql.ROWID cuss s computbe wth the dutubuse ROWID type. 1he ROWID
contuns the physcu uddress ol u row n the dutubuse. 1he loowng exumpe creutes un
oracle.sql.ROWID obect numed rowid:
oracle.sql.ROWID rowid;
Thc uracIc.jdbc Packagc
1he cusses und nterluces ol the oracle.jdbc puckuge uow you to reud und wrte coumn
vuues n the dutubuse vu oracle.sql obects. 1he oracle.jdbc puckuge uso contuns u
number ol perlormunce enhuncements. ln ths secton, you' eurn ubout the contents ol the
oracle.jdbc puckuge und see how to creute u row n the customers tube. 1hen you' eurn
how to reud thut row usng oracle.sql obects.
S72
Cruce Dutubuse ll SQL
Thc CIasscs and lntcrfaccs uf thc uracIc.jdbc Packagc
1ube l5-7 shows the cusses und nterluces ol the oracle.jdbc puckuge.
Using an OracIcPrcparcdStatcmcnt Objcct
1he OraclePreparedStatement nterluce mpements java.sql.PreparedStatement.
1hs nterluce supports the vurous set methods lor bndng oracle.sql obects.
ln the prevous secton, you suw the loowng oracle.sql obects:
An oracle.sql.NUMBER obect numed customerId, whch wus set to 6
An oracle.sql.CHAR obect numed firstName, whch wus set to Jason
Another oracle.sql.CHAR obect numed lastName, whch wus set to Price
An oracle.sql.DATE obect numed dob, whch wus set to 1969-02-22 13:54:12
1o use these obects n un SQL DML stutement, you must use un
OraclePreparedStatement obect, whch contuns set methods to hunde oracle.sql
obects. 1he loowng exumpe creutes un OraclePreparedStatement numed
myPrepStatement, whch w be used uter to udd u row to the customers tube:
OraclePreparedStatement myPrepStatement =
(OraclePreparedStatement) myConnection.prepareStatement(
"INSERT INTO customers " +
"(customer_id, first_name, last_name, dob, phone) VALUES (" +
"?, ?, ?, ?, ?" +
")"
);
Notce thut the PreparedStatement obect returned by the prepareStatement()
method s cust to un OraclePreparedStatement obect und s stored n myPrepStatement.
1he next step s to bnd the oracle.sql obects to myPrepStatement usng the set
methods. 1hs nvoves ussgnng vuues to the pucehoders murked by queston murk (?)
churucters n myPrepStatement. }ust us you use set methods ke setInt(), setFloat(),
setString(), und setDate() to bnd }uvu vurubes to u PreparedStatement obect, you
uso use set methods to bnd oracle.sql obects to un OraclePreparedStatement obect
(these set methods ncude setNUMBER(), setCHAR(), setDATE(), und so on).
1he loowng exumpe ustrute how to bnd the customerId, firstName, lastName,
und dob obects to myPrepStatement usng the upproprute set methods:
myPrepStatement.setNUMBER(1, customerId);
myPrepStatement.setCHAR(2, firstName);
myPrepStatement.setCHAR(3, lastName);
myPrepStatement.setDATE(4, dob);
1he next exumpe sets the llth queston murk (?) n myPrepStatement to NULL (the llth
queston murk (?) corresponds to the phone coumn n the customers tube):
myPrepStatement.setNull(5, OracleTypes.CHAR);
Chupter l5: Runnng SQL Lsng }uvu
S73
Namc CIass ur lntcrfacc Dcscriptiun
OracleDriver
Cuss lmpements java.sql.Driver.
You nput un obect ol ths cuss when
regsterng the Cruce }DC drvers usng
the registerDriver() method ol the
java.sql.DriverManager cuss.
OracleConnection
lnterluce lmpements java.sql.Connection.
1hs nterluce extends the stundurd
}DC connecton lunctonuty to use
OracleStatement obects. lt uso
mproves perlormunce over the stundurd
}DC lunctons.
OracleStatement lnterluce lmpements java.sql.Statement
und s the supercuss ol the
OraclePreparedStatement und
OracleCallableStatement cusses.
OraclePreparedStatement
lnterluce lmpements java.sql
.PreparedStatement,
und s the supercuss ol
OracleCallableStatement. 1hs
nterluce supports the vurous set
methods lor bndng oracle.sql
obects.
OracleCallableStatement lnterluce lmpements java.sql
.CallableStatement. 1hs nterluce
contuns vurous get und set methods
lor bndng oracle.sql obects.
OracleResultSet
lnterluce lmpements java.sql.ResultSet.
1hs nterluce contuns vurous get
methods lor bndng oracle.sql
obects.
OracleResultSetMetaData
lnterluce lmpements java.sql
.ResultSetMetaData. 1hs nterluce
contuns methods lor retrevng metu dutu
ubout Cruce resut sets (such us coumn
numes und ther types).
OracleDatabaseMetaData Cuss lmpements java.sql
.DatabaseMetaData. 1hs cuss
contuns methods lor retrevng metu dutu
ubout the Cruce dutubuse (such us the
dutubuse soltwure verson).
OracleTypes Cuss Delnes nteger constunts lor the dutubuse
types. 1hs cuss dupcutes the stundurd
java.sql.Types cuss und contuns
uddtonu nteger constunts lor u ol the
Cruce types.
TABlf 1S-7 Cac and n|cr|acc o| |hc oracle.jdbc ac|agc
S74
Cruce Dutubuse ll SQL
1he int constunt OracleTypes.CHAR specles thut the dutubuse type s computbe wth
the oracle.sql.CHAR type, OracleTypes.CHAR s used becuuse the phone coumn s u
VARCHAR2.
1he ony thng elt to do s to run the INSERT stutement usng the execute() method:
myPrepStatement.execute();
Dong ths udds the row to the customers tube.
Using an OracIcRcsuItSct Objcct
1he OracleResultSet nterluce mpements java.sql.ResultSet und contuns get methods
to hunde oracle.sql obects. ln ths secton, you' see how to use un OracleResultSet obect
to retreve the row prevousy udded to the customers tube.
1he lrst thng needed s u }DC Statement obect through whch un SQL stutement muy be run:
Statement myStatement = myConnection.createStatement();
Next, the loowng exumpe creutes un OracleResultSet obect numed
customerResultSet, whch s popuuted wth the ROWID, customer_id, first_
name, last_dob, und phone coumns retreved lrom customer r6:
OracleResultSet customerResultSet =
(OracleResultSet) myStatement.executeQuery(
"SELECT ROWID, customer_id, first_name, last_name, dob, phone " +
"FROM customers " +
"WHERE customer_id = 6"
);
l delned the loowng oracle.sql obects eurer: rowid, customerId, firstName,
lastName, und dob. 1hese muy be used to hod the lrst lve coumn vuues. ln order to store
the vuue lor the phone coumn, un oracle.sql.CHAR obect s needed:
oracle.sql.CHAR phone = new oracle.sql.CHAR("", myCharSet);
An OracleResultSet obect contuns get methods thut return oracle.sql obects.
You use getCHAR() to get un oracle.sql.CHAR, getNUMBER() to get un oracle.sql
.NUMBER, getDATE() to get un oracle.sql.DATE, und so on.
1he loowng while oop contuns cus to the upproprute get methods to copy the vuues
lrom customerResultSet to rowid, customerId, firstName, lastName, dob, und phone:
while (customerResultSet.next()) {
rowid = customerResultSet.getROWID("ROWID");
customerId = customerResultSet.getNUMBER("customer_id");
firstName = customerResultSet.getCHAR("first_name");
lastName = customerResultSet.getCHAR("last_name");
dob = customerResultSet.getDATE("dob");
phone = customerResultSet.getCHAR("phone");
System.out.println("rowid = " + rowid.stringValue());
System.out.println("customerId = " + customerId.stringValue());
System.out.println("firstName = " + firstName);
System.out.println("lastName = " + lastName);
System.out.println("dob = " + dob.stringValue());
Chupter l5: Runnng SQL Lsng }uvu
S7S
System.out.println("phone = " + phone);
} // end of while loop
1o dspuy the vuues, the exumpe uses cus to the stringValue() method to convert the
rowid, customerId, und dob obects to }uvu String vuues. lor the firstName, lastName,
und phone obects, the exumpe smpy uses these obects drecty n the System.out
.println() cus.
1he loowng secton shows u compete progrum contunng the stutements shown n the
prevous sectons.
fxampIc Prugram: BasicfxampIc3.java
1he loowng BasicExample3.java progrum contuns the stutements shown n the prevous
sectons:
/*
BasicExample3.java shows how to use the Oracle JDBC extensions
to add a row to the customers table, and then retrieve that row
*/
// import the JDBC packages
import java.sql.*;
// import the Oracle JDBC extension packages
import oracle.sql.*;
import oracle.jdbc.*;
public class BasicExample3 {
public static void main (String args []) {
try {
// register the Oracle JDBC drivers
DriverManager.registerDriver(
new oracle.jdbc.OracleDriver()
);
// EDIT AS NECESSARY TO CONNECT TO YOUR DATABASE
// create a Connection object, and connect to the database
// as the store user using the Oracle JDBC Thin driver
Connection myConnection = DriverManager.getConnection(
"jdbc:oracle:thin:@localhost:1521:ORCL",
"store",
"store_password"
);
// disable auto-commit mode
myConnection.setAutoCommit(false);
// create an oracle.sql.NUMBER object
oracle.sql.NUMBER customerId = new oracle.sql.NUMBER(6);
int customerIdInt = customerId.intValue();
System.out.println("customerIdInt = " + customerIdInt);
// create two oracle.sql.CHAR objects

Cruce Dutubuse ll SQL
oracle.sql.CharacterSet myCharSet =
CharacterSet.make(CharacterSet.US7ASCII_CHARSET);
oracle.sql.CHAR firstName = new oracle.sql.CHAR("Jason", myCharSet);
String firstNameString = firstName.stringValue();
System.out.println("firstNameString = " + firstNameString);
oracle.sql.CHAR lastName = new oracle.sql.CHAR("Price", myCharSet);
System.out.println("lastName = " + lastName);
// create an oracle.sql.DATE object
oracle.sql.DATE dob = new oracle.sql.DATE("1969-02-22 13:54:12");
String dobString = dob.stringValue();
System.out.println("dobString = " + dobString);
// create an OraclePreparedStatement object
OraclePreparedStatement myPrepStatement =
(OraclePreparedStatement) myConnection.prepareStatement(
"INSERT INTO customers " +
"(customer_id, first_name, last_name, dob, phone) VALUES (" +
"?, ?, ?, ?, ?" +
")"
);
// bind the objects to the OraclePreparedStatement using the
// appropriate set methods
myPrepStatement.setNUMBER(1, customerId);
myPrepStatement.setCHAR(2, firstName);
myPrepStatement.setCHAR(3, lastName);
myPrepStatement.setDATE(4, dob);
// set the phone column to NULL
myPrepStatement.setNull(5, OracleTypes.CHAR);
// run the PreparedStatement
myPrepStatement.execute();
System.out.println("Added row to customers table");
// retrieve the ROWID, customer_id, first_name, last_name, dob, and
// phone columns for this new row using an OracleResultSet
// object
Statement myStatement = myConnection.createStatement();
OracleResultSet customerResultSet =
(OracleResultSet) myStatement.executeQuery(
"SELECT ROWID, customer_id, first_name, last_name, dob, phone " +
"FROM customers " +
"WHERE customer_id = 6"
);
System.out.println("Retrieved row from customers table");
// declare an oracle.sql.ROWID object to store the ROWID, and
// an oracle.sql.CHAR object to store the phone column
oracle.sql.ROWID rowid;
oracle.sql.CHAR phone = new oracle.sql.CHAR("", myCharSet);
Chupter l5: Runnng SQL Lsng }uvu

// display the column values for row using the


// get methods to read the values
while (customerResultSet.next()) {
rowid = customerResultSet.getROWID("ROWID");
customerId = customerResultSet.getNUMBER("customer_id");
firstName = customerResultSet.getCHAR("first_name");
lastName = customerResultSet.getCHAR("last_name");
dob = customerResultSet.getDATE("dob");
phone = customerResultSet.getCHAR("phone");
System.out.println("rowid = " + rowid.stringValue());
System.out.println("customerId = " + customerId.stringValue());
System.out.println("firstName = " + firstName);
System.out.println("lastName = " + lastName);
System.out.println("dob = " + dob.stringValue());
System.out.println("phone = " + phone);
} // end of while loop
// close the OracleResultSet object using the close() method
customerResultSet.close();
// roll back the changes made to the database
myConnection.rollback();
// close the other JDBC objects
myPrepStatement.close();
myConnection.close();
} catch (SQLException e) {
System.out.println("Error code = " + e.getErrorCode());
System.out.println("Error message = " + e.getMessage());
System.out.println("SQL state = " + e.getSQLState());
e.printStackTrace();
}
} // end of main()
}
1he output lrom ths progrum s us loows:
customerIdInt = 6
firstNameString = Jason
lastName = Price
dobString = 2/22/1969 13:54:12
Added row to customers table
Retrieved row from customers table
rowid = AAARk5AAEAAAAGPAAF
customerId = 6
firstName = Jason
lastName = Price
dob = 2/22/1969 13:54:12
phone = null
dobString2 = 2/22/1969 0:0:0
S78
Cruce Dutubuse ll SQL
Summary
ln ths chupter, you huve eurned the loowng:
1he }DC All enubes u }uvu progrum to uccess u dutubuse.
1he Cruce }DC drvers ure used to connect to un Cruce dutubuse.
SQL stutements muy be executed usng }DC.
Cruce hus deveoped u number ol extensons to stundurd }DC thut uow you to gun
uccess to u ol the Cruce dutubuse types.
ln the next chupter, you' eurn how to tune your SQL stutements lor muxmum perlormunce.
\IAI1II
1o
SQL 1unng
579
S80
Cruce Dutubuse ll SQL
n ths chupter, you w do the loowng:
Leurn ubout SQL tunng
See SQL tunng tps thut you cun use to shorten the ength ol tme your queres tuke
to execute
Leurn ubout the Cruce optmzer
See how to compure the cost ol perlormng queres
Lxumne optmzer hnts
Leurn ubout some uddtonu tunng toos
lntruducing SQl Tuning
Cne ol the mun strengths ol SQL s thut you don't huve to te the dutubuse exucty how to obtun
the dutu requested. You smpy run u query speclyng the nlormuton you wunt, und the dutubuse
soltwure lgures out the best wuy to get t. Sometmes, you cun mprove the perlormunce ol your
SQL stutements by tunng them. ln the loowng sectons, you' see tunng tps thut cun muke
your queres run luster, uter, you' see more udvunced tunng technques.
Usc a WHfRf CIausc tu fiItcr Ruws
Muny novces retreve u the rows lrom u tube when they ony wunt one row (or u lew rows). 1hs
s very wustelu. A better upprouch s to udd u WHERE cuuse to u query. 1hut wuy, you restrct the
rows retreved to ust those uctuuy needed.
lor exumpe, suy you wunt the detus lor customer rl und r2. 1he loowng query retreves
u the rows lrom the customers tube n the store schemu (wustelu):
-- BAD (retrieves all rows from the customers table)
SELECT *
FROM customers;
CUSTOMER_ID FIRST_NAME LAST_NAME DOB PHONE
----------- ---------- ---------- --------- ------------
1 John Brown 01-JAN-65 800-555-1211
2 Cynthia Green 05-FEB-68 800-555-1212
3 Steve White 16-MAR-71 800-555-1213
4 Gail Black 800-555-1214
5 Doreen Blue 20-MAY-70
1he next query udds u WHERE cuuse to the prevous exumpe to ust get customer rl und r2:
-- GOOD (uses a WHERE clause to limit the rows retrieved)
SELECT *
FROM customers
WHERE customer_id IN (1, 2);

Chupter l6: SQL 1unng


S81
CUSTOMER_ID FIRST_NAME LAST_NAME DOB PHONE
----------- ---------- ---------- --------- ------------
1 John Brown 01-JAN-65 800-555-1211
2 Cynthia Green 05-FEB-68 800-555-1212
You shoud uvod usng lunctons n the WHERE cuuse, us thut ncreuses executon tme.
Usc TabIc |uins Rathcr than MuItipIc Qucrics
ll you need nlormuton lrom mutpe reuted tubes, you shoud use on condtons ruther thun
mutpe queres. ln the loowng bud exumpe, two queres ure used to get the product nume und
the product type nume lor product rl (usng two queres s wustelu). 1he lrst query gets the name
und product_type_id coumn vuues lrom the products tube lor product rl. 1he second
query then uses thut product_type_id to get the name coumn lrom the product_types tube.
-- BAD (two separate queries when one would work)
SELECT name, product_type_id
FROM products
WHERE product_id = 1;
NAME PRODUCT_TYPE_ID
------------------------------ ---------------
Modern Science 1
SELECT name
FROM product_types
WHERE product_type_id = 1;
NAME
----------
Book
lnsteud ol usng the two queres, you shoud wrte one query thut uses u on between the
products und product_types tubes. 1he loowng good query shows ths:
-- GOOD (one query with a join)
SELECT p.name, pt.name
FROM products p, product_types pt
WHERE p.product_type_id = pt.product_type_id
AND p.product_id = 1;
NAME NAME
------------------------------ ----------
Modern Science Book
1hs query resuts n the sume product nume und product type nume beng retreved us n the
lrst exumpe, but the resuts ure obtuned usng one query. Cne query s generuy more ellcent
thun two.
You shoud choose the on order n your query so thut you on lewer rows to tubes uter n
the on order. lor exumpe, suy you were onng three reuted tubes numed tab1, tab2, und
tab3. Assume tab1 contuns l,000 rows, tab2 l00 rows, und tab3 l0 rows. You shoud on
tab1 wth tab2 lrst, loowed by tab2 und tab3.
S82
Cruce Dutubuse ll SQL
Aso, uvod onng compex vews n your queres, becuuse dong so cuuses the queres lor
the vews to be run lrst, loowed by your uctuu query. lnsteud, wrte your query usng the tubes
ruther thun the vews.
Usc fuIIy QuaIificd CuIumn Rcfcrcnccs Whcn
Pcrfurming |uins
Awuys ncude tube uuses n your queres und use the uus lor euch coumn n your query (ths
s known us luy quulyng your coumn relerences). 1hut wuy, the dutubuse doesn't huve to
seurch lor euch coumn n the tubes used n your query.
1he loowng bud exumpe uses the uuses p und pt lor the products und product_
types tubes, respectvey, but the query doesn't luy quuly the description und price
coumns:
-- BAD (description and price columns not fully qualified)
SELECT p.name, pt.name, description, price
FROM products p, product_types pt
WHERE p.product_type_id = pt.product_type_id
AND p.product_id = 1;
NAME NAME
------------------------------ ----------
DESCRIPTION PRICE
-------------------------------------------------- ----------
Modern Science Book
A description of modern science 19.95
1hs exumpe works, but the dutubuse hus to seurch both the products und product_types
tubes lor the description und price coumns, thut's becuuse there's no uus thut tes the
dutubuse whch tube those coumns ure n. 1he extru tme spent by the dutubuse huvng to do the
seurch s wusted tme.
1he loowng good exumpe ncudes the tube uus p to luy quuly the description und
price coumns:
-- GOOD (all columns are fully qualified)
SELECT p.name, pt.name, p.description, p.price
FROM products p, product_types pt
WHERE p.product_type_id = pt.product_type_id
AND p.product_id = 1;
NAME NAME
------------------------------ ----------
DESCRIPTION PRICE
-------------------------------------------------- ----------
Modern Science Book
A description of modern science 19.95
ecuuse u relerences to coumns ncude u tube uus, the dutubuse doesn't huve to wuste
tme seurchng the tubes lor the coumns, und executon tme s reduced.
Chupter l6: SQL 1unng
S83
Usc CASf fxprcssiuns Rathcr than MuItipIc Qucrics
Lse CASE expressons ruther thun mutpe queres when you need to perlorm muny cucuutons
on the sume rows n u tube. 1he loowng bud exumpe uses mutpe queres to count the
number ol products wthn vurous prce runges:
-- BAD (three separate queries when one CASE statement would work)
SELECT COUNT(*)
FROM products
WHERE price < 13;
COUNT(*)
----------
2
SELECT COUNT(*)
FROM products
WHERE price BETWEEN 13 AND 15;
COUNT(*)
----------
5
SELECT COUNT(*)
FROM products
WHERE price > 15;
COUNT(*)
----------
5
Ruther thun usng three queres, you shoud wrte one query thut uses CASE expressons. 1hs
s shown n the loowng good exumpe:
-- GOOD (one query with a CASE expression)
SELECT
COUNT(CASE WHEN price < 13 THEN 1 ELSE null END) low,
COUNT(CASE WHEN price BETWEEN 13 AND 15 THEN 1 ELSE null END) med,
COUNT(CASE WHEN price > 15 THEN 1 ELSE null END) high
FROM products;
LOW MED HIGH
---------- ---------- ----------
2 5 5
Notce thut the counts ol the products wth prces ess thun Sl3 ure ubeed us low, products
between Sl3 und Sl5 ure ubeed med, und products greuter thun Sl5 ure ubeed high.
NOTf
You can, o| courc, uc ovcrappng rangc and d||crcn| |unc|on n
,our CASE cxprcon.
S84
Cruce Dutubuse llg SQL
Add lndcxcs tu TabIcs
\hen ookng lor u purtcuur topc n u book, you cun ether scun the whoe book or use the ndex
to lnd the ocuton. An ndex lor u dutubuse tube s smur n concept to u book ndex, except
thut dutubuse ndexes ure used to lnd speclc rows n u tube. 1he downsde ol ndexes s thut
when u row s udded to the tube, uddtonu tme s requred to updute the ndex lor the new row.
Ceneruy, you shoud creute un ndex on u coumn when you ure retrevng u smu number
ol rows lrom u tube contunng muny rows. A good rue ol thumb s
Crca|c an ndcx vhcn a qucr, rc|rcvc <= 10 pcrccn| o| |hc |o|a rov n a |abc.
1hs meuns the coumn lor the ndex shoud contun u wde runge ol vuues. A good cunddute
lor ndexng woud be u coumn contunng u unque vuue lor euch row (lor exumpe, u socu
securty number). A poor cunddute lor ndexng woud be u coumn thut contuns ony u smu
runge ol vuues (lor exumpe, N, S, L, \ or l, 2, 3, 4, 5, 6). An Cruce dutubuse uutomutcuy
creutes un ndex lor the prmury key ol u tube und lor coumns ncuded n u unque construnt.
ln uddton, l your dutubuse s uccessed usng u ot ol herurchcu queres (thut s, u query
contunng u CONNECT BY), you shoud udd ndexes to the coumns relerenced n the START
WITH und CONNECT BY cuuses (see Chupter 7 lor detus on herurchcu queres).
lnuy, lor u coumn thut contuns u smu runge ol vuues und s lrequenty used n the WHERE
cuuse ol queres, you shoud consder uddng u btmup ndex to thut coumn. tmup ndexes ure
typcuy used n dutu wurehouses, whch ure dutubuses contunng very urge umounts ol dutu.
1he dutu n u dutu wurehouse s typcuy reud usng muny queres, but the dutu s not modled
by muny concurrent trunsuctons.
Normuy, u dutubuse udmnstrutor s responsbe lor creutng ndexes. However, us un
uppcuton deveoper, you' be ube to provde the DA wth leedbuck on whch coumns ure
good cunddutes lor ndexng, becuuse you muy know more ubout the uppcuton thun the DA.
Chupter l0 covers ndexes n depth, und you shoud re-reud the secton on ndexes l necessury.
Usc WHfRf Rathcr than HAVlNG
You use the WHERE cuuse to lter rows, you use the HAVING cuuse to lter groups ol rows.
ecuuse the HAVING cuuse lters groups ol rows a||cr they huve been grouped together (whch
tukes some tme to do), you shoud lrst lter rows usng u WHERE cuuse whenever possbe. 1hut
wuy, you uvod the tme tuken to group the ltered rows together n the lrst puce.
1he loowng bud query retreves the product_type_id und uveruge prce lor products
whose product_type_id s l or 2. 1o do ths, the query perlorms the loowng:
lt uses the GROUP BY cuuse to group rows nto bocks wth the sume product_type_id.
lt uses the HAVING cuuse to lter the returned resuts to those groups thut huve u
product_type_id n l or 2 (ths s bud, becuuse u WHERE cuuse woud work).
-- BAD (uses HAVING rather than WHERE)
SELECT product_type_id, AVG(price)
FROM products
GROUP BY product_type_id
HAVING product_type_id IN (1, 2);
Chupter l6: SQL 1unng
S8S
PRODUCT_TYPE_ID AVG(PRICE)
--------------- ----------
1 24.975
2 26.22
1he loowng good query rewrtes the prevous exumpe to use WHERE ruther thun HAVING to
lrst lter the rows to those whose product_type_id s l or 2:
-- GOOD (uses WHERE rather than HAVING)
SELECT product_type_id, AVG(price)
FROM products
WHERE product_type_id IN (1, 2)
GROUP BY product_type_id;
PRODUCT_TYPE_ID AVG(PRICE)
--------------- ----------
1 24.975
2 26.22
Usc UNlON All Rathcr than UNlON
You use UNION ALL to get u the rows retreved by two queres, ncudng dupcute rows, you
use UNION to get u non-dupcute rows retreved by the queres. ecuuse UNION removes
dupcute rows (whch tukes some tme to do), you shoud use UNION ALL whenever possbe.
1he loowng bud query uses UNION (bud becuuse UNION ALL woud work) to get the rows
lrom the products und more_products tubes, notce thut u non-dupcute rows lrom
products und more_products ure retreved:
-- BAD (uses UNION rather than UNION ALL)
SELECT product_id, product_type_id, name
FROM products
UNION
SELECT prd_id, prd_type_id, name
FROM more_products;
PRODUCT_ID PRODUCT_TYPE_ID NAME
---------- --------------- -------------------
1 1 Modern Science
2 1 Chemistry
3 2 Supernova
3 Supernova
4 2 Lunar Landing
4 2 Tank War
5 2 Submarine
5 2 Z Files
6 2 2412: The Return
7 3 Space Force 9
8 3 From Another Planet
9 4 Classical Music
10 4 Pop 3
11 4 Creative Yell
12 My Front Line
S86
Cruce Dutubuse ll SQL
1he loowng good query rewrtes the prevous exumpe to use UNION ALL, notce thut u
the rows lrom products und more_products ure retreved, ncudng dupcutes:
-- GOOD (uses UNION ALL rather than UNION)
SELECT product_id, product_type_id, name
FROM products
UNION ALL
SELECT prd_id, prd_type_id, name
FROM more_products;
PRODUCT_ID PRODUCT_TYPE_ID NAME
---------- --------------- ------------------------------
1 1 Modern Science
2 1 Chemistry
3 2 Supernova
4 2 Tank War
5 2 Z Files
6 2 2412: The Return
7 3 Space Force 9
8 3 From Another Planet
9 4 Classical Music
10 4 Pop 3
11 4 Creative Yell
12 My Front Line
1 1 Modern Science
2 1 Chemistry
3 Supernova
4 2 Lunar Landing
5 2 Submarine
Usc fXlSTS Rathcr than lN
You use IN to check l u vuue s contuned n u st. You use EXISTS to check lor the exstence ol
rows returned by u subquery. EXISTS s dllerent lrom IN: EXISTS ust checks lor the exstence
ol rows, whereus IN checks uctuu vuues. EXISTS typcuy ollers better perlormunce thun IN
wth subqueres. 1herelore, you shoud use EXISTS ruther thun IN whenever possbe.
You shoud reler buck to the secton entted Lsng LXlS1S und NC1 LXlS1S wth u Correuted
Subquery n Chupter 6 lor lu detus on when you shoud use EXISTS wth u correuted subquery
(un mportunt pont to remember s thut correuted subqueres cun resove nu vuues).
1he loowng bud query uses IN (bud becuuse EXISTS woud work) to retreve products thut
huve been purchused:
-- BAD (uses IN rather than EXISTS)
SELECT product_id, name
FROM products
WHERE product_id IN
(SELECT product_id
FROM purchases);
PRODUCT_ID NAME
---------- -----------------------------
1 Modern Science
Chupter l6: SQL 1unng
S87
2 Chemistry
3 Supernova
1he loowng good query rewrtes the prevous exumpe to use EXISTS:
-- GOOD (uses EXISTS rather than IN)
SELECT product_id, name
FROM products outer
WHERE EXISTS
(SELECT 1
FROM purchases inner
WHERE inner.product_id = outer.product_id);
PRODUCT_ID NAME
---------- -----------------------------
1 Modern Science
2 Chemistry
3 Supernova
Usc fXlSTS Rathcr than DlSTlNCT
You cun suppress the dspuy ol dupcute rows usng DISTINCT. You use EXISTS to check lor the
exstence ol rows returned by u subquery. \henever possbe, you shoud use EXISTS ruther thun
DISTINCT, becuuse DISTINCT sorts the retreved rows belore suppressng the dupcute rows.
1he loowng bud query uses DISTINCT (bud becuuse EXISTS woud work) to retreve
products thut huve been purchused:
-- BAD (uses DISTINCT when EXISTS would work)
SELECT DISTINCT pr.product_id, pr.name
FROM products pr, purchases pu
WHERE pr.product_id = pu.product_id;
PRODUCT_ID NAME
---------- -----------------------------
1 Modern Science
2 Chemistry
3 Supernova
1he loowng good query rewrtes the prevous exumpe to use EXISTS ruther thun DISTINCT:
-- GOOD (uses EXISTS rather than DISTINCT)
SELECT product_id, name
FROM products outer
WHERE EXISTS
(SELECT 1
FROM purchases inner
WHERE inner.product_id = outer.product_id);
PRODUCT_ID NAME
---------- -----------------------------
1 Modern Science
2 Chemistry
3 Supernova
S88
Cruce Dutubuse llg SQL
Usc GROUPlNG SfTS Rathcr than CUBf
1he GROUPING SETS cuuse typcuy ollers better perlormunce thun CUBE. 1herelore, you
shoud use GROUPING SETS ruther thun CUBE wherever possbe. 1hs s luy covered n the
secton entted Lsng the CRCLllNC SL1S Cuuse n Chupter 7.
Usc Bind VariabIcs
1he Cruce dutubuse soltwure cuches SQL stutements, u cuched SQL stutement s reused l un
dentcu stutement s submtted to the dutubuse. \hen un SQL stutement s reused, the executon
tme s reduced. However, the SQL stutement must be abou|c, dcn|ca n order lor t to be
reused. 1hs meuns thut
A churucters n the SQL stutement must be the sume.
A etters n the SQL stutement must be n the sume cuse.
A spuces n the SQL stutement must be the sume.
ll you need to suppy dllerent coumn vuues n u stutement, you cun use bnd vurubes
nsteud ol teru coumn vuues. You' see exumpes thut curly these deus next.
Nun-ldcnticaI SQl Statcmcnts
ln ths secton, you' see some non-dentcu SQL stutements. 1he loowng non-dentcu queres
retreve products rl und r2:
SELECT * FROM products WHERE product_id = 1;
SELECT * FROM products WHERE product_id = 2;
1hese queres ure not dentcu, becuuse the vuue l s used n the lrst stutement, but the
vuue 2 s used n the second.
1he loowng non-dentcu queres huve spuces n dllerent postons:
SELECT * FROM products WHERE product_id = 1;
SELECT * FROM products WHERE product_id = 1;
1he loowng non-dentcu queres use u dllerent cuse lor some ol the churucters:
select * from products where product_id = 1;
SELECT * FROM products WHERE product_id = 1;
Now thut you've seen some non-dentcu stutements, et's tuke u ook ut dentcu SQL
stutements thut use bnd vurubes.
ldcnticaI SQl Statcmcnts That Usc Bind VariabIcs
You cun ensure thut u stutement s dentcu by usng bnd vurubes to represent coumn vuues.
You creute u bnd vurube usng the SQL*lus VARIABLE commund. lor exumpe, the loowng
commund creutes u vurube numed v_product_id ol type NUMBER:
VARIABLE v_product_id NUMBER
Chupter l6: SQL 1unng
S89
NOTf
You can uc |hc |,pc hovn n Tabc A-1 o| |hc appcndx |o dc|nc
|hc |,pc o| a bnd varabc.
You relerence u bnd vurube n un SQL or lL/SQL stutement usng u coon loowed by the
vurube nume (such us :v_product_id). lor exumpe, the loowng lL/SQL bock sets v_
product_id to l:
BEGIN
:v_product_id := 1;
END;
/
1he loowng query uses v_product_id to set the product_id coumn vuue n the
WHERE cuuse, becuuse v_product_id wus set to l n the prevous lL/SQL bock, the query
retreves the detus ol product rl:
SELECT * FROM products WHERE product_id = :v_product_id;
PRODUCT_ID PRODUCT_TYPE_ID NAME
---------- --------------- ------------------------------
DESCRIPTION PRICE
-------------------------------------------------- ----------
1 1 Modern Science
A description of modern science 19.95
1he next exumpe sets v_product_id to 2 und repeuts the query:
BEGIN
:v_product_id := 2;
END;
/
SELECT * FROM products WHERE product_id = :v_product_id;
PRODUCT_ID PRODUCT_TYPE_ID NAME
---------- --------------- ------------------------------
DESCRIPTION PRICE
-------------------------------------------------- ----------
2 1 Chemistry
Introduction to Chemistry 30
ecuuse the query used n ths exumpe s dentcu to the prevous query, the cuched query s
reused und there's un mprovement n perlormunce.
TlP
You houd |,pca, uc bnd varabc | ,ou'rc pcr|ormng |hc amc
qucr, man, |mc. Ao, n |hc cxampc, |hc bnd varabc arc con
pcc|c and nccd |o bc rcc| | |hc con o|.
S90
Cruce Dutubuse ll SQL
listing and Printing Bind VariabIcs
You st bnd vurubes n SQL*lus usng the VARIABLE commund. lor exumpe:
VARIABLE
variable v_product_id
datatype NUMBER
You dspuy the vuue ol u bnd vurube n SQL*lus usng the PRINT commund. lor
exumpe:
PRINT v_product_id
V_PRODUCT_ID
-------------
2
Using a Bind VariabIc tu Sturc a VaIuc Rcturncd
by a Pl/SQl functiun
You cun uso use u bnd vurube to store returned vuues lrom u lL/SQL luncton. 1he loowng
exumpe creutes u bnd vurube numed v_average_product_price und stores the resut
returned by the luncton average_product_price() (ths luncton wus descrbed n Chupter ll
und cucuutes the uveruge product prce lor the supped product_type_id):
VARIABLE v_average_product_price NUMBER
BEGIN
:v_average_product_price := average_product_price(1);
END;
/
PRINT v_average_product_price
V_AVERAGE_PRODUCT_PRICE
------------------------
24.975
Using a Bind VariabIc tu Sturc Ruws frum a RffCURSOR
You cun uso use u bnd vurube to store returned vuues lrom u REFCURSOR (u REFCURSOR s u
ponter to u st ol rows). 1he loowng exumpe creutes u bnd vurube numed v_products_
refcursor und stores the resut returned by the luncton product_package.get_products_
ref_cursor() (ths luncton wus ntroduced n Chupter ll, t returns u ponter to the rows n the
products tube):
VARIABLE v_products_refcursor REFCURSOR
BEGIN
:v_products_refcursor := product_package.get_products_ref_cursor();
END;
/
PRINT v_products_refcursor
PRODUCT_ID NAME PRICE
---------- ------------------------------ ----------
1 Modern Science 19.95
2 Chemistry 30
Chupter l6: SQL 1unng
S91
3 Supernova 25.99
4 Tank War 13.95
5 Z Files 49.99
6 2412: The Return 14.95
7 Space Force 9 13.49
8 From Another Planet 12.99
9 Classical Music 10.99
10 Pop 3 15.99
11 Creative Yell 14.99
PRODUCT_ID NAME PRICE
---------- ------------------------------ ----------
12 My Front Line 13.49
Cumparing thc Cust uf Pcrfurming Qucrics
1he Cruce dutubuse soltwure uses u subsystem known us the op|m2cr to generute the most
ellcent puth to uccess the dutu stored n the tubes. 1he puth generuted by the optmzer s
known us un cxccu|on pan. Cruce Dutubuse l0g und ubove uutomutcuy guthers stutstcs
ubout the dutu n your tubes und ndexes n order to generute the best executon pun (ths s
known us co|-bacd optmzuton).
Compurng the executon puns generuted by the optmzer uows you to udge the reutve
cost ol one SQL stutement versus unother. You cun use the resuts to mprove your SQL stutements.
ln ths secton, you' eurn how to vew und nterpret u coupe ol exumpe executon puns.
NOTf
Da|abac vcron pror |o Cracc Da|abac 10g don'| au|oma|ca,
ga|hcr |a||c, and |hc op|m2cr au|oma|ca, dc|au| |o rue-bused
op|m2a|on. Ruc-bacd op|m2a|on uc ,n|ac|c ruc |o gcncra|c
|hc cxccu|on pan. Co|-bacd op|m2a|on |,pca, bc||cr |han
ruc-bacd op|m2a|on bccauc |hc |ormcr uc ac|ua n|orma|on
ga|hcrcd |rom |hc da|a n |hc |abc and ndcxc. | ,ou'rc ung
Cracc Da|abac 9 or bcov, ,ou can ga|hcr |a||c ,ourc| (,ou'
carn hov |o do |ha| a|cr n |hc cc|on Ca|hcrng Tabc S|a||c").
fxamining fxccutiun PIans
1he optmzer generutes un executon pun lor un SQL stutement. You cun exumne the executon
pun usng the SQL*lus EXPLAIN PLAN commund. 1he EXPLAIN PLAN commund popuutes
u tube numed plan_table wth the SQL stutement's executon pun (plan_table s olten
relerred to us the pun tube). You muy then exumne thut executon pun by queryng the pun
tube. 1he lrst thng you must do s check l the pun tube currenty exsts n the dutubuse.
Chccking if thc PIan TabIc CurrcntIy fxists in thc Databasc
1o check l the pun tube currenty exsts n the dutubuse, you shoud connect to the dutubuse us
the store user und run the loowng DESCRIBE commund:
SQL> DESCRIBE plan_table
Name Null? Type
----------------------------------------- -------- --------------
STATEMENT_ID VARCHAR2(30)
S92
Cruce Dutubuse llg SQL
PLAN_ID NUMBER
TIMESTAMP DATE
REMARKS VARCHAR2(4000)
OPERATION VARCHAR2(30)
OPTIONS VARCHAR2(255)
OBJECT_NODE VARCHAR2(128)
OBJECT_OWNER VARCHAR2(30)
OBJECT_NAME VARCHAR2(30)
OBJECT_ALIAS VARCHAR2(65)
OBJECT_INSTANCE NUMBER(38)
OBJECT_TYPE VARCHAR2(30)
OPTIMIZER VARCHAR2(255)
SEARCH_COLUMNS NUMBER
ID NUMBER(38)
PARENT_ID NUMBER(38)
DEPTH NUMBER(38)
POSITION NUMBER(38)
COST NUMBER(38)
CARDINALITY NUMBER(38)
BYTES NUMBER(38)
OTHER_TAG VARCHAR2(255)
PARTITION_START VARCHAR2(255)
PARTITION_STOP VARCHAR2(255)
PARTITION_ID NUMBER(38)
OTHER LONG
OTHER_XML CLOB
DISTRIBUTION VARCHAR2(30)
CPU_COST NUMBER(38)
IO_COST NUMBER(38)
TEMP_SPACE NUMBER(38)
ACCESS_PREDICATES VARCHAR2(4000)
FILTER_PREDICATES VARCHAR2(4000)
PROJECTION VARCHAR2(4000)
TIME NUMBER(38)
QBLOCK_NAME VARCHAR2(30)
ll you get u tube descrpton smur to these resuts, you huve the pun tube ureudy. ll you
get un error, then you need to creute the pun tube.
Crcating thc PIan TabIc
ll you don't huve the pun tube, you must creute t. 1o do ths, you run the SQL*lus scrpt
utlxplan.sql (on my \ndows computer, the scrpt s ocuted n the drectory E:\oracle_
11g\product\11.1.0\db_1\RDBMS\ADMIN). 1he loowng exumpe shows the commund
to run the utlxplan.sql scrpt:
SQL> @ E:\oracle_11g\product\11.1.0\db_1\RDBMS\ADMIN\utlxplan.sql
NOTf
You' nccd |o rcpacc |hc drcc|or, pa|h v|h |hc pa|h |or ,our
cnvronmcn|.
1he most mportunt coumns n the pun tube ure shown n 1ube l6-l.
Chupter l6: SQL 1unng
S93
Crcating a CcntraI PIan TabIc
ll necessury, u dutubuse udmnstrutor cun creute one centru pun tube. 1hut wuy,
ndvduu users don't huve to creute ther own pun tubes. 1o do ths, u dutubuse
udmnstrutor perlorms the loowng steps:
1. Creutes the pun tube n u schemu ol ther choce by runnng the utlxplan.sql
scrpt
2. Creutes u pubc synonym lor the pun tube
3. Crunts uccess on the pun tube to the pubc roe
Here s un exumpe ol these steps:
@ E:\oracle_11g\product\11.1.0\db_1\RDBMS\ADMIN\utlxplan.sql
CREATE PUBLIC SYNONYM plan_table FOR plan_table;
GRANT SELECT, INSERT, UPDATE, DELETE ON plan_table TO PUBLIC;
CuIumn Dcscriptiun
statement_id
Nume you ussgn to the executon pun.
operation
Dutubuse operuton perlormed, whch cun be
Scunnng u tube
Scunnng un ndex
Accessng rows lrom u tube by usng un ndex
}onng two tubes together
Sortng u row set
lor exumpe, the operuton lor uccessng u tube s TABLE ACCESS.
options
Nume ol the opton used n the operuton. lor exumpe, the opton lor u
compete scun s FULL.
object_name
Nume ol the dutubuse obect relerenced n the operuton.
object_type
Attrbute ol obect. lor exumpe, u unque ndex hus the uttrbute ol
UNIQUE.
id
Number ussgned to ths operuton n the executon pun.
parent_id
lurent number lor the current step n the executon pun. 1he parent_
id vuue reutes to un id vuue lrom u purent step.
position
lrocessng order lor steps thut huve the sume parent_id.
cost
Lstmute ol unts ol work lor operuton. Cost-bused optmzuton uses
dsk l/C, ClL usuge, und memory usuge us unts ol work. 1herelore, the
cost s un estmute ol the number ol dsk l/Cs und the umount ol ClL
und memory used n perlormng un operuton.
TABlf 16-1 an Tabc Coumn
S94
Cruce Dutubuse llg SQL
Gcncrating an fxccutiun PIan
Cnce you huve u pun tube, you cun use the EXPLAIN PLAN commund to generute un executon
pun lor un SQL stutement. 1he syntux lor the EXPLAIN PLAN commund s us loows:
EXPLAIN PLAN SET STATEMENT_ID = statement_id FOR sql_statement;
where
statement_id s the nume you wunt to cu the executon pun. 1hs cun be uny
uphunumerc text.
sql_statement s the SQL stutement you wunt to generute un executon pun lor.
1he loowng exumpe generutes the executon pun lor u query thut retreves u rows lrom
the customers tube (notce thut the statement_id s set to 'CUSTOMERS'):
EXPLAIN PLAN SET STATEMENT_ID = 'CUSTOMERS' FOR
SELECT customer_id, first_name, last_name FROM customers;
Explained
Alter the commund competes, you muy exumne the executon pun stored n the pun tube.
You' see how to do thut next.
NOTf
Thc qucr, n |hc EXPLAIN PLAN |a|cmcn| docn'| rc|urn rov
|rom |hc customers |abc. Thc EXPLAIN PLAN |a|cmcn| mp,
gcncra|c |hc cxccu|on pan |ha| voud bc ucd | |hc qucr, va run.
Qucrying thc PIan TabIc
lor queryng the pun tube, l huve provded un SQL*lus scrpt numed explain_plan.sql n
the SQL drectory. 1he scrpt prompts you lor the statement_id und then dspuys the executon
pun lor thut stutement.
1he explain_plan.sql scrpt s us loows:
-- Displays the execution plan for the specified statement_id
UNDEFINE v_statement_id;
SELECT
id ||
DECODE(id, 0, '', LPAD(' ', 2*(level - 1))) || ' ' ||
operation || ' ' ||
options || ' ' ||
object_name || ' ' ||
object_type || ' ' ||
DECODE(cost, NULL, '', 'Cost = ' || position)
AS execution_plan
FROM plan_table
CONNECT BY PRIOR id = parent_id
AND statement_id = '&&v_statement_id'
START WITH id = 0
AND statement_id = '&v_statement_id';
Chupter l6: SQL 1unng

An executon pun s orgunzed nto u herurchy ol dutubuse operutons smur to u tree, the
detus ol these operutons ure stored n the pun tube. 1he operuton wth un id ol 0 s the root
ol the herurchy, und u the other operutons n the pun stem lrom ths root. 1he query n the
scrpt retreves the detus ol the operutons, sturtng wth the root operuton und then nuvgutng
the tree lrom the root.
1he loowng exumpe shows how to run the explain_plan.sql scrpt to retreve the
'CUSTOMERS' pun creuted eurer:
SQL> @ c:\sql_book\sql\explain_plan.sql
Enter value for v_statement_id: CUSTOMERS
old 12: statement_id = '&&v_statement_id'
new 12: statement_id = 'CUSTOMERS'
old 14: statement_id = '&v_statement_id'
new 14: statement_id = 'CUSTOMERS'
EXECUTION_PLAN
----------------------------------------------
0 SELECT STATEMENT Cost = 3
1 TABLE ACCESS FULL CUSTOMERS TABLE Cost = 1
1he operutons shown n the EXECUTION_PLAN coumn ure executed n the loowng order:
1he rghtmost ndented operuton s executed lrst, loowed by uny purent operutons
ubove t.
lor operutons wth the sume ndentuton, the topmost operuton s executed lrst,
loowed by uny purent operutons ubove t.
Luch operuton leeds ts resuts buck up the chun to ts mmedute purent operuton, und the
purent operuton s then executed. ln the EXECUTION_PLAN coumn, the operuton lD s shown
on the lur elt. ln the exumpe executon pun, operuton l s run lrst, wth the resuts ol thut
operuton beng pussed to operuton 0. 1he loowng exumpe ustrutes the orderng lor u more
compex exumpe:
0 SELECT STATEMENT Cost = 6
1 MERGE JOIN Cost = 1
2 TABLE ACCESS BY INDEX ROWID PRODUCT_TYPES TABLE Cost = 1
3 INDEX FULL SCAN PRODUCT_TYPES_PK INDEX (UNIQUE) Cost = 1
4 SORT JOIN Cost = 2
5 TABLE ACCESS FULL PRODUCTS TABLE Cost = 1
1he order n whch the operutons ure executed n ths exumpe s 3, 2, 5, 4, l, und 0.
Now thut you've seen the order n whch operutons ure executed, t's tme to move onto whut
the operutons uctuuy do. 1he executon pun lor the 'CUSTOMERS' query wus
0 SELECT STATEMENT Cost = 3
1 TABLE ACCESS FULL CUSTOMERS TABLE Cost = 1
Cperuton l s run lrst, wth the resuts ol thut operuton beng pussed to operuton 0.
Cperuton l nvoves u lu tube scunndcuted by the strng TABLE ACCESS FULLon the
customers tube. Here's the orgnu commund used to generute the 'CUSTOMERS' query:
EXPLAIN PLAN SET STATEMENT_ID = 'CUSTOMERS' FOR
SELECT customer_id, first_name, last_name FROM customers;
S96
Cruce Dutubuse llg SQL
A lu tube scun s perlormed becuuse the SELECT stutement specles thut u the rows lrom
the customers tube ure to be retreved.
1he totu cost ol the query s three work unts, us ndcuted n the cost purt shown to the rght
ol operuton 0 n the executon pun (0 SELECT STATEMENT Cost = 3). A work unt s the
umount ol processng the soltwure hus to do to perlorm u gven operuton. 1he hgher the cost,
the more work the dutubuse soltwure hus to do to compete the SQL stutement.
NOTf
| ,ou'rc ung a vcron o| |hc da|abac pror |o Cracc Da|abac 10g,
|hcn |hc ou|pu| |or |hc ovcra |a|cmcn| co| ma, bc ban|. Tha|'
bccauc carcr da|abac vcron don'| au|oma|ca, cocc| |abc
|a||c. n ordcr |o ga|hcr |a||c, ,ou havc |o uc |hc ANALYZE
command. You' carn hov |o do |ha| a|cr n |hc cc|on Ca|hcrng
Tabc S|a||c."
fxccutiun PIans lnvuIving TabIc |uins
Lxecuton puns lor queres wth tube ons ure more compex. 1he loowng exumpe generutes
the executon pun lor u query thut ons the products und product_types tubes:
EXPLAIN PLAN SET STATEMENT_ID = 'PRODUCTS' FOR
SELECT p.name, pt.name
FROM products p, product_types pt
WHERE p.product_type_id = pt.product_type_id;
1he executon pun lor ths query s shown n the loowng exumpe:
@ c:\sql_book\sql\explain_plan.sql
Enter value for v_statement_id: PRODUCTS
EXECUTION_PLAN
----------------------------------------------------------------
0 SELECT STATEMENT Cost = 6
1 MERGE JOIN Cost = 1
2 TABLE ACCESS BY INDEX ROWID PRODUCT_TYPES TABLE Cost = 1
3 INDEX FULL SCAN PRODUCT_TYPES_PK INDEX (UNIQUE) Cost = 1
4 SORT JOIN Cost = 2
5 TABLE ACCESS FULL PRODUCTS TABLE Cost = 1
NOTf
| ,ou run |hc cxampc, ,ou ma, gc| a gh|, d||crcn| cxccu|on
pan dcpcndng on |hc vcron o| |hc da|abac ,ou arc ung and
on |hc c||ng o| |hc paramc|cr n |hc da|abac' init.ora
con|gura|on |c.
1he prevous executon pun s more compex, und you cun see the herurchcu reutonshps
between the vurous operutons. 1he executon order ol the operutons s 3, 2, 5, 4, l, und 0. 1ube
l6-2 descrbes euch operuton n the order they ure perlormed.
Chupter l6: SQL 1unng
S97
Gathcring TabIc Statistics
ll you're usng u verson ol the dutubuse pror to Cruce Dutubuse l0g (such us 9 ), then you'
huve to guther tube stutstcs yoursel usng the ANALYZE commund. y deluut, l no stutstcs ure
uvuube then rue-bused optmzuton s used. Rue-bused optmzuton sn't usuuy us good us
cost-bused optmzuton.
1he loowng exumpes use the ANALYZE commund to guther stutstcs lor the products
und product_types tubes:
ANALYZE TABLE products COMPUTE STATISTICS;
ANALYZE TABLE product_types COMPUTE STATISTICS;
Cnce the stutstcs huve been guthered, cost-bused optmzuton w be used ruther thun rue-
bused optmzuton.
Cumparing fxccutiun PIans
y compurng the totu cost shown n the executon pun lor dllerent SQL stutements, you cun
determne the vuue ol tunng your SQL. ln ths secton, you' see how to compure two executon
puns und see the benelt ol usng EXISTS ruther thun DISTINCT (u tp l guve eurer). 1he loowng
exumpe generutes un executon pun lor u query thut uses EXISTS:
EXPLAIN PLAN SET STATEMENT_ID = 'EXISTS_QUERY' FOR
SELECT product_id, name
FROM products outer
WHERE EXISTS
(SELECT 1
FROM purchases inner
WHERE inner.product_id = outer.product_id);
Opcratiun lD Dcscriptiun
3 lu scun ol the ndex product_types_pk (whch s u unque ndex)
to obtun the uddresses ol the rows n the product_types tube. 1he
uddresses ure n the lorm ol ROWID vuues, whch ure pussed to operuton 2.
2 Access the rows n the product_types tube usng the st ol ROWID
vuues pussed lrom operuton 3. 1he rows ure pussed to operuton l.
5 Access the rows n the products tube. 1he rows ure pussed to operuton 4.
4 Sort the rows pussed lrom operuton 5. 1he sorted rows ure pussed to
operuton l.
l Merge the rows pussed lrom operutons 2 und 5. 1he merged rows ure
pussed to operuton 0.
0 Return the rows lrom operuton l to the user. 1he totu cost ol the query s
6 work unts.
TABlf 16-2 xccu|on an Cpcra|on
S98
Cruce Dutubuse ll SQL
1he executon pun lor ths query s shown n the loowng exumpe:
@ c:\sql_book\sql\explain_plan.sql
Enter value for v_statement_id: EXISTS_QUERY
EXECUTION_PLAN
------------------------------------------------------------
0 SELECT STATEMENT Cost = 4
1 MERGE JOIN SEMI Cost = 1
2 TABLE ACCESS BY INDEX ROWID PRODUCTS TABLE Cost = 1
3 INDEX FULL SCAN PRODUCTS_PK INDEX (UNIQUE) Cost = 1
4 SORT UNIQUE Cost = 2
5 INDEX FULL SCAN PURCHASES_PK INDEX (UNIQUE) Cost = 1
As you cun see, the totu cost ol the query s 4 work unts. 1he next exumpe generutes un
executon pun lor u query thut uses DISTINCT:
EXPLAIN PLAN SET STATEMENT_ID = 'DISTINCT_QUERY' FOR
SELECT DISTINCT pr.product_id, pr.name
FROM products pr, purchases pu
WHERE pr.product_id = pu.product_id;
1he executon pun lor ths query s shown n the loowng exumpe:
@ c:\sql_book\sql\explain_plan.sql
Enter value for v_statement_id: DISTINCT_QUERY
EXECUTION_PLAN
--------------------------------------------------------------
0 SELECT STATEMENT Cost = 5
1 HASH UNIQUE Cost = 1
2 MERGE JOIN Cost = 1
3 TABLE ACCESS BY INDEX ROWID PRODUCTS TABLE Cost = 1
4 INDEX FULL SCAN PRODUCTS_PK INDEX (UNIQUE) Cost = 1
5 SORT JOIN Cost = 2
6 INDEX FULL SCAN PURCHASES_PK INDEX (UNIQUE) Cost = 1
1he cost lor the query s 5 work unts. 1hs query s more costy thun the eurer query thut
used EXISTS (thut query hud u cost ol ony 4 work unts). 1hese resuts prove t s better to use
EXISTS thun DISTINCT.
Passing Hints tu thc Optimizcr
You cun puss hnts to the optmzer. A hnt s un optmzer drectve thut nluences the optmzer's
choce ol executon pun. 1he correct hnt muy mprove the perlormunce ol un SQL stutement.
You cun check the ellectveness ol u hnt by compurng the cost n the executon pun ol un SQL
stutement wth und wthout the hnt.
ln ths secton, you' see un exumpe query thut uses one ol the more uselu hnts: the
FIRST_ROWS(n) hnt. 1he FIRST_ROWS(n) hnt tes the optmzer to generute un executon
pun thut w mnmze the tme tuken to return the lrst n rows n u query. 1hs hnt cun be uselu
when you don't wunt to wut uround too ong belore gettng rows buck lrom your query, but
you st wunt to see u the rows.
Chupter l6: SQL 1unng
S99
1he loowng exumpe generutes un executon pun lor u query thut uses FIRST_ROWS(2),
notce thut the hnt s puced wthn the strngs /*+ und */:
EXPLAIN PLAN SET STATEMENT_ID = 'HINT' FOR
SELECT /*+ FIRST_ROWS(2) */ p.name, pt.name
FROM products p, product_types pt
WHERE p.product_type_id = pt. product_type_id;
CAUTlON
Your hn| mu| uc |hc exuct ,n|ax hovno|hcrvc, |hc hn|
v bc gnorcd. Thc ,n|ax : /*+ |oovcd b, onc pacc, |hc
hn|, |oovcd b, onc pacc, and */.
1he executon pun lor ths query s shown n the loowng exumpe, notce thut the cost s
4 work unts:
@ c:\sql_book\sql\explain_plan.sql
Enter value for v_statement_id: HINT
EXECUTION_PLAN
------------------------------------------------------------------
0 SELECT STATEMENT Cost = 4
1 NESTED LOOPS
2 NESTED LOOPS Cost = 1
3 TABLE ACCESS FULL PRODUCTS TABLE Cost = 1
4 INDEX UNIQUE SCAN PRODUCT_TYPES_PK INDEX (UNIQUE) Cost = 2
5 TABLE ACCESS BY INDEX ROWID PRODUCT_TYPES TABLE Cost = 2
1he next exumpe generutes un executon pun lor the sume query wthout the hnt:
EXPLAIN PLAN SET STATEMENT_ID = 'NO_HINT' FOR
SELECT p.name, pt.name
FROM products p, product_types pt
WHERE p.product_type_id = pt. product_type_id;
1he executon pun lor the query s shown n the loowng exumpe, notce the cost s 6 work
unts (hgher thun the query wth the hnt):
@ c:\sql_book\sql\explain_plan.sql
Enter value for v_statement_id: NO_HINT
EXECUTION_PLAN
----------------------------------------------------------------
0 SELECT STATEMENT Cost = 6
1 MERGE JOIN Cost = 1
2 TABLE ACCESS BY INDEX ROWID PRODUCT_TYPES TABLE Cost = 1
3 INDEX FULL SCAN PRODUCT_TYPES_PK INDEX (UNIQUE) Cost = 1
4 SORT JOIN Cost = 2
5 TABLE ACCESS FULL PRODUCTS TABLE Cost = 1
1hese resuts show thut the ncuson ol the hnt reduces the cost ol runnng the query by
2 work unts.
600
Cruce Dutubuse llg SQL
1here ure muny hnts thut you cun use, und ths secton hus merey gven you u tuste ol the
subect.
AdditiunaI Tuning TuuIs
ln ths lnu secton, l' menton some other tunng toos. lu coveruge ol these toos s beyond
the scope ol ths book. You cun reud the Cracc Da|abac cr|ormancc Tunng Cudc, pubshed
by Cruce Corporuton, lor lu detus ol the toos mentoned n ths secton und lor u comprehensve
st ol hnts.
OracIc fntcrprisc Managcr Diagnustics Pack
1he Cruce Lnterprse Munuger Dugnostcs luck cuptures operutng system, mdde ter, und
uppcuton perlormunce dutu, us we us dutubuse perlormunce dutu. 1he Dugnostcs luck
unuyzes ths perlormunce dutu und dspuys the resuts gruphcuy. A dutubuse udmnstrutor cun
uso conlgure the Dugnostcs luck to uert them mmedutey ol perlormunce probems vu e-mu
or puge. Cruce Lnterprse Munuger uso ncudes soltwure gudes to hep resove perlormunce
probems.
Autumatic Databasc Diagnustic Munitur
1he Automutc Dutubuse Dugnostc Montor (ADDM) s u sel-dugnostc modue but nto the
Cruce dutubuse soltwure. ADDM enubes u dutubuse udmnstrutor to montor the dutubuse lor
perlormunce probems by unuyzng system perlormunce over u ong perod ol tme. 1he dutubuse
udmnstrutor cun vew the perlormunce nlormuton generuted by ADDM n Cruce Lnterprse
Munuger. \hen ADDM lnds perlormunce probems, t w suggest soutons lor correctve
ucton. Some exumpe ADDM suggestons ncude
Hurdwure chungeslor exumpe, uddng ClLs to the dutubuse server
Dutubuse conlgurutonlor exumpe, chungng the dutubuse ntuzuton purumeter
settngs
Appcuton chungeslor exumpe, usng the cuche opton lor sequences or usng bnd
vurubes
Lse other udvsorslor exumpe, runnng the SQL 1unng Advsor und SQL Access
Advsor on SQL stutements thut ure consumng the most dutubuse resources to execute
You' eurn ubout the SQL 1unng Advsor und SQL Access Advsor next.
SQl Tuning Advisur
1he SQL 1unng Advsor uows u deveoper or dutubuse udmnstrutor to tune un SQL stutement
usng the loowng tems:
1he text ol the SQL stutement
1he SQL dentler ol the stutement (obtuned lrom the V$SQL_PLAN vew, whch s one
ol the vews uvuube to u dutubuse udmnstrutor)
1he runge ol snupshot dentlers
1he SQL 1unng Set nume
Chupter l6: SQL 1unng
601
An SQL 1unng Set s u set ol SQL stutements wth ther ussocuted executon pun und executon
stutstcs. SQL 1unng Sets ure unuyzed to generute SQL lroles thut hep the optmzer to choose
the optmu executon pun. SQL lroles contun coectons ol nlormuton thut enube optmzuton
ol the executon pun.
SQl Acccss Advisur
1he SQL Access Advsor provdes u deveoper or dutubuse udmnstrutor wth perlormunce udvce
on muteruzed vews, ndexes, und muteruzed vew ogs. 1he SQL Access Advsor exumnes
spuce usuge und query perlormunce und recommends the most cost-ellectve conlguruton ol
new und exstng muteruzed vews und ndexes.
Summary
ln ths chupter, you huve eurned the loowng:
1unng s the process ol mukng your SQL stutements run luster.
1he optmzer s u subsystem ol the Cruce dutubuse soltwure thut generutes un executon
pun, whch s u set ol operutons used to perlorm u purtcuur SQL stutement.
Hnts muy be pussed to the optmzer to nluence the generuted executon pun lor un
SQL stutement.
1here ure u number ol uddtonu soltwure toos u dutubuse udmnstrutor cun use to tune
the dutubuse.
ln the next chupter, you' eurn ubout XML.
This page intentionally left blank
\IAI1II
17
XML und the Cruce
Dutubuse
603
604
Cruce Dutubuse ll SQL
n ths chupter, you w do the loowng:
ecome ntroduced to XML
See how to generute XML lrom reutonu dutu
Lxumne how to suve XML n the dutubuse
lntruducing XMl
1he Lxtensbe Murkup Lunguuge (XML) s u generu-purpose murkup unguuge. XML enubes you
to shure structured dutu ucross the lnternet, und cun be used to encode dutu und other documents.
Some udvuntuges ol XML ncude the loowng:
XML cun be reud by humuns und computers, und s stored us pun text.
XML s putlorm ndependent.
XML supports Lncode, whch meuns t cun store nlormuton wrtten n muny humun
unguuges.
XML uses u sel-documentng lormut thut contuns the document structure, eement
numes, und eement vuues.
ecuuse ol these udvuntuges, XML s wdey used lor document storuge und processng, und t
s used by muny orgunzutons to send dutu between ther computer systems. lor exumpe, muny
suppers uow ther customers to send purchuse orders us XML les over the lnternet.
Cruce Dutubuse 9 ntroduced the ubty to store XML n the dutubuse, uong wth extensve
lunctonuty lor munpuutng und processng XML. Cruce Dutubuse l0 Reeuse 2 udded
uddtonu XML-generutng lunctons, und Cruce Dutubuse ll udds cupubtes ke }uvu und C
processng ol bnury XML (bnury XML provdes more ellcent storuge und munpuuton ol XML
n the dutubuse). 1hs chupter locuses on u uselu subset ol the XML cupubtes n the Cruce
dutubuse.
ll you ure new to XML, you w lnd u weuth ol nlormuton ut the loowng webstes:
http://www.w3.org/XML
http://www.wkpedu.org/wk/XML
Gcncrating XMl frum RcIatiunaI Data
1he Cruce dutubuse contuns u number ol SQL lunctons you cun use lor generutng XML, und n
ths secton you' see how to generute XML lrom reutonu dutu usng some ol these lunctons.

Chupter l7: XML und the Cruce Dutubuse


60S
XMlflfMfNT()
You use the XMLELEMENT() luncton to generute XML eements lrom reutonu dutu. You suppy
u nume lor the eement, pus the coumn you wsh to retreve to XMLELEMENT(), und t returns
the eements us XMLType obects. 1he XMLType s u but-n Cruce dutubuse type thut s used to
represent XML dutu. y deluut, un XMLType obect stores the XML dutu us text n u CLC (churucter
urge obect).
1he loowng exumpe connects us the store user und gets the customer_id coumn
vuues us XMLType obects:
CONNECT store/store_password
SELECT XMLELEMENT("customer_id", customer_id)
AS xml_customers
FROM customers;
XML_CUSTOMERS
----------------------------
<customer_id>1</customer_id>
<customer_id>2</customer_id>
<customer_id>3</customer_id>
<customer_id>4</customer_id>
<customer_id>5</customer_id>
As you cun see lrom these resuts, XMLELEMENT("customer_id", customer_id)
returns the customer_id vuues wthn u customer_id tug. You cun use whutever tug nume
you wunt, us shown n the loowng exumpe whch uses the tug "cust_id":
SELECT XMLELEMENT("cust_id", customer_id)
AS xml_customers
FROM customers;
XML_CUSTOMERS
--------------------
<cust_id>1</cust_id>
<cust_id>2</cust_id>
<cust_id>3</cust_id>
<cust_id>4</cust_id>
<cust_id>5</cust_id>
1he next exumpe gets the first_name und dob vuues lor customer r2:
SELECT XMLELEMENT("first_name", first_name) || XMLELEMENT("dob", dob)
AS xml_customer
FROM customers
WHERE customer_id = 2;
XML_CUSTOMER
-----------------------------------------------------
<first_name>Cynthia</first_name><dob>1968-02-05</dob>

Cruce Dutubuse llg SQL
1he loowng exumpe uses the TO_CHAR() luncton to chunge the dute lormut lor the dob
vuue:
SELECT XMLELEMENT("dob", TO_CHAR(dob, 'MM/DD/YYYY'))
AS xml_dob
FROM customers
WHERE customer_id = 2;
XML_DOB
---------------------
<dob>02/05/1968</dob>
1he next exumpe embeds two cus to XMLELEMENT() wthn un outer cu to XMLELEMENT(),
notce thut the returned customer_id und name eements ure contuned wthn un outer
customer eement:
SELECT XMLELEMENT(
"customer",
XMLELEMENT("customer_id", customer_id),
XMLELEMENT("name", first_name || ' ' || last_name)
)
AS xml_customers
FROM customers
WHERE customer_id IN (1, 2);
XML_CUSTOMERS
------------------------------
<customer>
<customer_id>1</customer_id>
<name>John Brown</name>
</customer>
<customer>
<customer_id>2</customer_id>
<name>Cynthia Green</name>
</customer>

'vc addcd omc nc brca| and pacc n |hc X\ rc|urncd b, |h


qucr, |o ma|c |hc X\ cacr |o rcad. 'vc donc |hc amc |hng n
omc o| |hc o|hcr cxampc n |h chap|cr.
You cun retreve reguur reutonu dutu us we us XML, us shown n the loowng exumpe,
whch retreves the customer_id coumn us u reguur reutonu resut und the first_name
und last_name coumns concutenuted together us XML eements:
SELECT customer_id,
XMLELEMENT("customer", first_name || ' ' || last_name) AS xml_customer
FROM customers;
Chupter l7: XML und the Cruce Dutubuse

CUSTOMER_ID XML_CUSTOMER
----------- ----------------------------------
1 <customer>John Brown</customer>
2 <customer>Cynthia Green</customer>
3 <customer>Steve White</customer>
4 <customer>Gail Black</customer>
5 <customer>Doreen Blue</customer>
You cun generute XML lor dutubuse obects, us shown n the next exumpe whch connects
us object_user und gets the id und address coumns lor customer rl n the object_
customers tube (the address coumn stores un obect ol type t_address):
CONNECT object_user/object_password
SELECT XMLELEMENT("id", id) || XMLELEMENT("address", address)
AS xml_object_customer
FROM object_customers
WHERE id = 1;
XML_OBJECT_CUSTOMER
-----------------------------------
<id>1</id>
<address>
<T_ADDRESS>
<STREET>2 State Street</STREET>
<CITY>Beantown</CITY>
<STATE>MA</STATE>
<ZIP>12345</ZIP>
</T_ADDRESS>
</address>
You cun generute XML lor coectons, us shown n the next exumpe, whch connects us
collection_user und gets the id und addresses coumns lor customer rl stored n
customers_with_nested_table (the addresses coumn stores un obect ol type t_
nested_table_address, whch s u nested tube ol t_address obects):
CONNECT collection_user/collection_password
SELECT XMLELEMENT("id", id) || XMLELEMENT("addresses", addresses)
AS xml_customer
FROM customers_with_nested_table
WHERE id = 1;
XML_CUSTOMER
---------------------------------------------------------
<id>1</id>
<addresses>
<T_NESTED_TABLE_ADDRESS>
<T_ADDRESS>
<STREET>2 State Street</STREET><CITY>Beantown</CITY>
<STATE>MA</STATE><ZIP>12345</ZIP>
</T_ADDRESS>
608
Cruce Dutubuse ll SQL
<T_ADDRESS>
<STREET>4 Hill Street</STREET>
<CITY>Lost Town</CITY>
<STATE>CA</STATE>
<ZIP>54321</ZIP>
</T_ADDRESS>
</T_NESTED_TABLE_ADDRESS>
</addresses>
XMlATTRlBUTfS()
You use XMLATTRIBUTES() n conuncton wth XMLELEMENT() to specly the uttrbutes lor the
XML eements retreved by XMLELEMENT(). 1he loowng exumpe connects us the store user
und uses XMLATTRIBUTES() to set uttrbute numes lor the customer_id, first_name,
last_name, und dob eements:
CONNECT store/store_password
SELECT XMLELEMENT(
"customer",
XMLATTRIBUTES(
customer_id AS "id",
first_name || ' ' || last_name AS "name",
TO_CHAR(dob, 'MM/DD/YYYY') AS "dob"
)
)
AS xml_customers
FROM customers
WHERE customer_id IN (1, 2);
XML_CUSTOMERS
------------------------------------------------------------------
<customer id="1" name="John Brown" dob="01/01/1965"></customer>
<customer id="2" name="Cynthia Green" dob="02/05/1968"></customer>
Notce thut the id, name, und dob uttrbutes ure returned nsde customer.
XMlfORfST()
You use XMLFOREST() to generute u lorest ol XML eements. XMLFOREST() concutenutes
XML eements together wthout you huvng to use the concutenuton operutor || wth mutpe
cus to XMLELEMENT(). 1he loowng exumpe uses XMLFOREST() to get the customer_id,
phone, und dob lor customers rl und r2:
SELECT XMLELEMENT(
"customer",
XMLFOREST(
customer_id AS "id",
phone AS "phone",
TO_CHAR(dob, 'MM/DD/YYYY') AS "dob"
)
)
AS xml_customers
Chupter l7: XML und the Cruce Dutubuse
609
FROM customers
WHERE customer_id IN (1, 2);
XML_CUSTOMERS
-----------------------------
<customer>
<id>1</id>
<phone>800-555-1211</phone>
<dob>01/01/1965</dob>
</customer>
<customer>
<id>2</id>
<phone>800-555-1212</phone>
<dob>02/05/1968</dob>
</customer>
1he loowng commund sets the SQL*lus LONG purumeter to 500, so you cun see u the
XML returned by the subsequent queres (LONG contros the muxmum ength ol text dutu
dspuyed by SQL*lus):
SET LONG 500
1he loowng query puces the customer nume nsde the customer eement tug usng
XMLATTRIBUTES():
SELECT XMLELEMENT(
"customer",
XMLATTRIBUTES(first_name || ' ' || last_name AS "name"),
XMLFOREST(phone AS "phone", TO_CHAR(dob, 'MM/DD/YYYY') AS "dob")
)
AS xml_customers
FROM customers
WHERE customer_id IN (1, 2);
XML_CUSTOMERS
-------------------------------
<customer name="John Brown">
<phone>800-555-1211</phone>
<dob>01/01/1965</dob>
</customer>
<customer name="Cynthia Green">
<phone>800-555-1212</phone>
<dob>02/05/1968</dob>
</customer>
XMlAGG()
You use XMLAGG() to generute u lorest ol XML eements lrom u coecton ol XML eements.
XMLAGG() s typcuy used lor groupng XML together nto u common st ol tems underneuth
one purent or lor retrevng dutu lrom coectons. You cun use the GROUP BY cuuse ol u query

Cruce Dutubuse ll SQL
to group the retuned set ol rows nto mutpe groups, und you cun use un ORDER BY cuuse ol
XMLAGG() to sort the rows.
y deluut, ORDER BY sorts the resuts n uscendng order, but you cun udd DESC ulter the st
ol coumns to sort the rows n descendng order. You cun udd ASC to expcty ndcute un uscendng
sort. You cun uso udd NULLS LAST to put uny nu vuues ut the end ol the resuts.
1he loowng exumpe retreves the customer first_name und last_name vuues und returns
them n u st numed customer_list, notce thut ORDER BY s used wth XMLAGG() to sort the
resuts by the first_name coumn. l've udded ASC to expcty ndcute un uscendng sort:
SELECT XMLELEMENT(
"customer_list",
XMLAGG(
XMLELEMENT("customer", first_name || ' ' || last_name)
ORDER BY first_name ASC
)
)
AS xml_customers
FROM customers
WHERE customer_id IN (1, 2);
XML_CUSTOMERS
------------------------------------
<customer_list>
<customer>Cynthia Green</customer>
<customer>John Brown</customer>
</customer_list>
1he next exumpe retreves the product_type_id und uveruge price lor euch group ol
products, notce thut the products ure grouped by product_type_id usng the GROUP BY
cuuse ol the query, und NULLS LAST s used n the ORDER BY cuuse ol XMLAGG() to puce
the row wth the nu product_type_id ut the end ol the returned resuts:
SELECT XMLELEMENT(
"product_list",
XMLAGG(
XMLELEMENT(
"product_type_and_avg", product_type_id || ' ' || AVG(price)
)
ORDER BY product_type_id NULLS LAST
)
)
AS xml_products
FROM products
GROUP BY product_type_id;
XML_PRODUCTS
-------------------------------------------------------
<product_list>
<product_type_and_avg>1 24.975</product_type_and_avg>
<product_type_and_avg>2 26.22</product_type_and_avg>
<product_type_and_avg>3 13.24</product_type_and_avg>
Chupter l7: XML und the Cruce Dutubuse

<product_type_and_avg>4 13.99</product_type_and_avg>
<product_type_and_avg> 13.49</product_type_and_avg>
</product_list>

You can ao pacc |hc nu rov |r| b, pcc|,ng NULLS FIRST n


|hc ORDER BY cauc o| XMLAGG().
1he next exumpe retreves the product_type_id und name lor the products wth
product_type_id vuues ol l und 2, und the products ure grouped by product_type_id:
SELECT XMLELEMENT(
"products_in_group",
XMLATTRIBUTES(product_type_id AS "prd_type_id"),
XMLAGG(
XMLELEMENT("name", name)
)
)
AS xml_products
FROM products
WHERE product_type_id IN (1, 2)
GROUP BY product_type_id;
XML_PRODUCTS
-----------------------------------
<products_in_group prd_type_id="1">
<name>Modern Science</name>
<name>Chemistry</name>
</products_in_group>
<products_in_group prd_type_id="2">
<name>Supernova</name>
<name>2412: The Return</name>
</products_in_group>
1he next exumpe connects us collection_user und retreves the uddresses lor customer
rl lrom customers_with_nested_table:
CONNECT collection_user/collection_password
SELECT XMLELEMENT("customer",
XMLAGG(
XMLELEMENT("addresses", addresses)
)
)
AS xml_customer
FROM customers_with_nested_table
WHERE id = 1;
XML_CUSTOMER
---------------------------------------
<customer>
<addresses>
612
Cruce Dutubuse ll SQL
<T_NESTED_TABLE_ADDRESS>
<T_ADDRESS>
<STREET>2 State Street</STREET>
<CITY>Beantown</CITY>
<STATE>MA</STATE>
<ZIP>21345</ZIP>
</T_ADDRESS>
<T_ADDRESS>
<STREET>4 Hill Street</STREET>
<CITY>Lost Town</CITY>
<STATE>CA</STATE>
<ZIP>54321</ZIP>
</T_ADDRESS>
</T_NESTED_TABLE_ADDRESS>
</addresses>
</customer>
XMlCOlATTVAl()
You use XMLCOLATTVAL() to creute un XML lrugment und then expund the resutng XML. Luch
XML lrugment hus the nume coumn wth the uttrbute nume. You cun use the AS cuuse to chunge
the uttrbute nume.
1he loowng exumpe connects us the store user retreves the customer_id, dob, und
phone vuues lor customers rl und r2:
CONNECT store/store_password
SELECT XMLELEMENT(
"customer",
XMLCOLATTVAL(
customer_id AS "id",
dob AS "dob",
phone AS "phone"
)
)
AS xml_customers
FROM customers
WHERE customer_id IN (1, 2);
XML_CUSTOMERS
----------------------------------------------
<customer>
<column name = "id">1</column>
<column name = "dob">1965-01-01</column>
<column name = "phone">800-555-1211</column>
</customer>
<customer>
<column name = "id">2</column>
<column name = "dob">1968-02-05</column>
<column name = "phone">800-555-1212</column>
</customer>
Chupter l7: XML und the Cruce Dutubuse
613
XMlCONCAT()
You use XMLCONCAT() to concutenute u seres ol eements lor euch row. 1he loowng exumpe
concutenutes the XML eements lor first_name, last_name, und phone vuues lor customers
rl und r2:
SELECT XMLCONCAT(
XMLELEMENT("first name", first_name),
XMLELEMENT("last name", last_name),
XMLELEMENT("phone", phone)
)
AS xml_customers
FROM customers
WHERE customer_id IN (1, 2);
XML_CUSTOMERS
--------------------------------
<first name>John</first name>
<last name>Brown</last name>
<phone>800-555-1211</phone>
<first name>Cynthia</first name>
<last name>Green</last name>
<phone>800-555-1212</phone>
XMlPARSf()
You use XMLPARSE() to purse und generute XML lrom the evuuuted resut ol un expresson. 1he
expresson must resove to u strng, l the expresson resoves to nu, then XMLPARSE() returns
nu. You must specly one ol the loowng tems belore the expresson:
CONTENT, whch meuns the expresson must resove to u vud XML vuue
DOCUMENT, whch meuns the expresson must resove to u sngy rooted XML document
You cun uso udd WELLFORMED ulter the expresson, whch meuns you ure guurunteeng thut
your expresson resoves to u we-lormed XML document. 1hs uso meuns thut the dutubuse w
not perlorm vudty checks on your expresson.
1he loowng exumpe purses un expresson contunng the detus lor u customer:
SELECT XMLPARSE(
CONTENT
'<customer><customer_id>1</customer_id><name>John Brown</name></customer>'
WELLFORMED
)
AS xml_customer
FROM dual;
XML_CUSTOMER
------------------------------
<customer>
<customer_id>1</customer_id>
<name>John Brown</name>
</customer>
614
Cruce Dutubuse llg SQL
NOTf
You can rcad morc abou| vc-|ormcd X\ documcn| and vauc a|
h||p://vvv.vJ.org/TR/RC-xm.
XMlPl()
You use XMLPI() to generute un XML processng nstructon. You typcuy use u processng
nstructon to provde un uppcuton wth nlormuton thut s ussocuted wth XML dutu, the
uppcuton cun then use the processng nstructon to determne how to process the XML dutu.
1he loowng exumpe generutes u processng nstructon lor un order stutus:
SELECT XMLPI(
NAME "order_status",
'PLACED, PENDING, SHIPPED'
)
AS xml_order_status_pi
FROM dual;
XML_ORDER_STATUS_PI
-----------------------------------------
<?order_status PLACED, PENDING, SHIPPED?>
1he next exumpe generutes u processng nstructon to dspuy un XML document usng u
cuscudng styesheet le numed example.css:
SELECT XMLPI(
NAME "xml-stylesheet",
'type="text/css" href="example.css"'
)
AS xml_stylesheet_pi
FROM dual;
XML_STYLESHEET_PI
-----------------------------------------------------
<?xml-stylesheet type="text/css" href="example.css"?>
XMlCOMMfNT()
You use XMLCOMMENT() to generute un XML comment, whch s u text strng puced wthn <!--
und -->. lor exumpe:
SELECT XMLCOMMENT(
'An example XML Comment'
)
AS xml_comment
FROM dual;
XML_COMMENT
-----------------------------
<!--An example XML Comment-->
Chupter l7: XML und the Cruce Dutubuse
61S
XMlSfQUfNCf()
You use XMLSEQUENCE() to generute un XMLSequenceType obect, whch s u vurruy ol
XMLType obects. ecuuse XMLSEQUENCE() returns u vurruy, you cun use t n the FROM
cuuse ol u query. lor exumpe:
SELECT VALUE(list_of_values).GETSTRINGVAL() order_values
FROM TABLE(
XMLSEQUENCE(
EXTRACT(
XMLType('<A><B>PLACED</B><B>PENDING</B><B>SHIPPED</B></A>'),
'/A/B'
)
)
) list_of_values;
ORDER_VALUES
--------------
<B>PLACED</B>
<B>PENDING</B>
<B>SHIPPED</B>
Let's breuk down ths exumpe. 1he cu to XMLType() s
XMLType('<A><B>PLACED</B><B>PENDING</B><B>SHIPPED</B></A>')
1hs creutes un XMLType obect contunng the XML
<A><B>PLACED</B><B>PENDING</B><B>SHIPPED</B></A>.
1he cu to the EXTRACT() luncton s
EXTRACT(
XMLType('<A><B>PLACED</B><B>PENDING</B><B>SHIPPED</B></A>'),
'/A/B'
)
EXTRACT() extructs the XML dutu lrom the XMLType obect returned by the cu to XMLType().
1he second purumeter to EXTRACT() s un Xluth strng. Xluth s u unguuge thut uows you uccess
speclc eements n XML dutu. lor exumpe, n the prevous cu to EXTRACT(), '/A/B' returns u
the eements thut ure chdren ol the A eements, therelore, the EXTRACT() luncton returns the
loowng:
<B>PLACED</B>
<B>PENDING</B>
<B>SHIPPED</B>
1he cu to XMLSEQUENCE() n the exumpe smpy returns u vurruy contunng the eements
returned by EXTRACT(). TABLE() converts the vurruy nto u tube ol rows und uppes the uus
list_of_values to the tube. 1he SELECT stutement retreves the strng vuue ol the rows n
the tube usng GETSTRINGVAL().
You' see more exumpes ol EXTRACT() und Xluth uter n ths chupter.
616
Cruce Dutubuse ll SQL
XMlSfRlAllZf()
You use XMLSERIALIZE() to generute u strng or LC (urge obect) representuton ol XML dutu
lrom the evuuuted resut ol un expresson. You must specly one ol the loowng tems belore the
expresson:
CONTENT, whch meuns the expresson must resove to u vud XML vuue
DOCUMENT, whch meuns the expresson must resove to u sngy rooted XML document
1he loowng exumpe uses XMLSERIALIZE() wth CONTENT to generute un XML vuue:
SELECT XMLSERIALIZE(
CONTENT XMLType('<order_status>SHIPPED</order_status>')
)
AS xml_order_status
FROM DUAL;
XML_ORDER_STATUS
------------------------------------
<order_status>SHIPPED</order_status>
1he next exumpe uses XMLSERIALIZE() wth DOCUMENT to generute un XML document,
wth the document returned n u CLC (churucter urge obect):
SELECT XMLSERIALIZE(
DOCUMENT XMLType('<description>Description of a product</description>')
AS CLOB
)
AS xml_product_description
FROM DUAL;
XML_PRODUCT_DESCRIPTION
---------------------------------------------------
<description>Description of a product</description>
A Pl/SQl fxampIc That Writcs XMl Data tu a fiIc
ln ths secton, you' see u compete lL/SQL exumpe thut wrtes customer numes to un XML
le. lrst, you need to connect us u prveged user (lor exumpe, the system user) und grunt
the CREATE ANY DIRECTORY prvege to the store user:
CONNECT system/manager;
GRANT CREATE ANY DIRECTORY TO store;
Next, you need to connect us the store user und creute u drectory obect:
CONNECT store/store_password;
CREATE DIRECTORY TEMP_FILES_DIR AS 'C:\temp_files';
You' uso need to creute u drectory numed temp_files n the C purtton. (ll you're usng
Lnux or Lnx, you cun creute the drectory on one ol your purttons und use un upproprute
CREATE DIRECTORY commund wth the correct puth. Aso, muke sure you grunt wrte
permssons on the drectory to the Cruce user uccount you used to nstu the dutubuse soltwure.)
Chupter l7: XML und the Cruce Dutubuse
617
Next, you need to run the xml_examples.sql scrpt ocuted n the SQL drectory, us shown
here:
@ "E:\Oracle SQL book\sql_book\SQL\xml_examples.sql"
CAUTlON
Run on, |hc xml_examples.sql crp| a| |h pon|. You ma, no|cc
|hcrc a crp| namcd xml_schema.sql n |hc SQL drcc|or,. Do
no| run xml_schema.sql ,c|.
1he xml_examples.sql scrpt creutes two procedures, the one you' see n ths secton s
numed write_xml_data_to_file(), whch retreves the customer numes und wrtes them to
un XML le. 1he write_xml_data_to_file() procedure s delned us loows:
CREATE PROCEDURE write_xml_data_to_file(
p_directory VARCHAR2,
p_file_name VARCHAR2
) AS
v_file UTL_FILE.FILE_TYPE;
v_amount INTEGER := 32767;
v_xml_data XMLType;
v_char_buffer VARCHAR2(32767);
BEGIN
-- open the file for writing of text (up to v_amount
-- characters at a time)
v_file := UTL_FILE.FOPEN(p_directory, p_file_name, 'w', v_amount);
-- write the starting line to v_file
UTL_FILE.PUT_LINE(v_file, '<?xml version="1.0"?>');
-- retrieve the customers and store them in v_xml_data
SELECT
EXTRACT(
XMLELEMENT(
"customer_list",
XMLAGG(
XMLELEMENT("customer", first_name || ' ' || last_name)
ORDER BY last_name
)
),
'/customer_list'
)
AS xml_customers
INTO v_xml_data
FROM customers;
-- get the string value from v_xml_data and store it in v_char_buffer
v_char_buffer := v_xml_data.GETSTRINGVAL();
-- copy the characters from v_char_buffer to the file
UTL_FILE.PUT(v_file, v_char_buffer);
618
Cruce Dutubuse ll SQL
-- flush any remaining data to the file
UTL_FILE.FFLUSH(v_file);
-- close the file
UTL_FILE.FCLOSE(v_file);
END write_xml_data_to_file;
/
1he loowng stutement cus write_xml_data_to_file():
CALL write_xml_data_to_file('TEMP_FILES_DIR', 'customers.xml');
Alter you run ths stutement, you' lnd u le numed customers.xml n C:\temp_files,
or whchever drectory you used when usng the CREATE DIRECTORY commund eurer. 1he
contents ol the customers.xml le s us loows:
<?xml version="1.0"?>
<customer_list><customer>Gail Black</customer><customer>Doreen Blue
</customer><customer>John Brown</customer><customer>Cynthia Green
</customer><customer>Steve White</customer></customer_list>
You cun modly the write_xml_data_to_file() procedure to retreve uny reutonu
dutu lrom the dutubuse und wrte t out to un XML le.
XMlQUfRY()
You use XMLQUERY() to construct XML or query XML. You puss un XQuery expresson to
XMLQUERY(). XQuery s u query unguuge thut uows you to construct und query XML.
XMLQUERY() returns the resut ol evuuutng the XQuery expresson.
1he loowng smpe exumpe ustrutes the use ol XMLQUERY():
SELECT XMLQUERY(
'(1, 2 + 5, "d", 155 to 161, <A>text</A>)'
RETURNING CONTENT
)
AS xml_output
FROM DUAL;
XML_OUTPUT
--------------------------------------------
1 7 d 155 156 157 158 159 160 161<A>text</A>
Here ure some notes lor the exumpe:
1he strng pussed to XMLQUERY() s the XQuery expresson, thut s, the XQuery
expresson s (1, 2 + 5, "d", 155 to 161, <A>text</A>). l s un nteger
teru, 2 + 5 s un urthmetc expresson, d s u strng teru, l55 to l6l s u sequence
ol ntegers, und <A>text</A> s un XML eement.
Luch ol the tems n the XQuery s evuuuted n turn. lor exumpe, 2 + 5 s evuuuted, und
7 s returned. Smury, l55 to l6l s evuuuted und l55 l56 l57 l58 l59 l60 l6l s
returned.
Chupter l7: XML und the Cruce Dutubuse

RETURNING CONTENT meuns un XML lrugment s returned. 1hs XML lrugment s u


snge XML eement wth uny number ol chdren, whch cun themseves be ol uny XML
eement type, ncudng text eements. 1he XML lrugment uso conlorms to the extended
lnloset dutu mode. lnloset s u speclcuton descrbng un ubstruct dutu mode ol un XML
document. You cun eurn more ubout lnloset ut http://www.w3.org/1R/xm-nloset.
Let's expore u more compex exumpe. 1he loowng stutement (contuned n the xml_
examples.sql scrpt) creutes u procedure numed create_xml_resources(), ths
procedure creutes XML strngs lor products und product types. lt uses methods n the lL/SQL
DBMS_XDB puckuge to deete und creute XML resource les n the Cruce XML D Repostory
(the XML D Repostory s u storuge ureu lor XML dutu wthn the dutubuse):
CREATE PROCEDURE create_xml_resources AS
v_result BOOLEAN;
-- create string containing XML for products
v_products VARCHAR2(300):=
'<?xml version="1.0"?>' ||
'<products>' ||
'<product product_id="1" product_type_id="1" name="Modern Science"'
|| ' price="19.95"/>' ||
'<product product_id="2" product_type_id="1" name="Chemistry"' ||
' price="30"/>' ||
'<product product_id="3" product_type_id="2" name="Supernova"' ||
' price="25.99"/>' ||
'</products>';
-- create string containing XML for product types
v_product_types VARCHAR2(300):=
'<?xml version="1.0"?>' ||
'<product_types>' ||
'<product_type product_type_id="1" name="Book"/>' ||
'<product_type product_type_id="2" name="Video"/>' ||
'</product_types>';
BEGIN
-- delete any existing resource for products
DBMS_XDB.DELETERESOURCE('/public/products.xml',
DBMS_XDB.DELETE_RECURSIVE_FORCE);
-- create resource for products
v_result := DBMS_XDB.CREATERESOURCE('/public/products.xml',
v_products);
-- delete any existing resource for product types
DBMS_XDB.DELETERESOURCE('/public/product_types.xml',
DBMS_XDB.DELETE_RECURSIVE_FORCE);
-- create resource for product types
v_result := DBMS_XDB.CREATERESOURCE('/public/product_types.xml',
v_product_types);
END create_xml_resources;
/

Cruce Dutubuse ll SQL
Here ure some notes lor create_xml_resources():
1he DBMS_XDB.DELETERESOURCE() procedure deetes un XML resource lrom the
dutubuse. 1hs procedure s cued by create_xml_resources() so thut you don't
huve to munuuy remove the resources l you run create_xml_resources() more
thun once.
1he DBMS_XDB.DELETE_RECURSIVE_FORCE constunt lorces the deeton ol the
resource, ncudng uny chd obects.
1he DBMS_XDB.CREATERESOURCE() luncton creutes un XML resource n the dutubuse
und returns u ooeun true/false vuue ndcutng whether the operuton wus successlu.
1he two cus to ths luncton creute resources lor the products und product types n /
public, whch s the ubsoute puth to store the resources.
1he loowng stutement cus create_xml_resources():
CALL create_xml_resources();
1he loowng query uses XMLQUERY() to retreve the products lrom the /public/
products.xml resource:
SELECT XMLQUERY(
'for $product in doc("/public/products.xml")/products/product
return <product name="{$product/@name}"/>'
RETURNING CONTENT
)
AS xml_products
FROM DUAL;
XML_PRODUCTS
-----------------------------------------
<product name="Modern Science"></product>
<product name="Chemistry"></product>
<product name="Supernova"></product>
1he XQuery expresson nsde XMLQUERY() n the prevous exumpe s
for $product in doc("/public/products.xml")/products/product
return <product name="{$product/@name}"/>
Let's breuk down ths XQuery expresson:
1he for oop terutes over the products n /public/products.xml.
$product s u bndng vurube thut s bound to the sequence ol products returned
by doc("/public/products.xml")/products/product, doc("/public/
products.xml") returns the products.xml document stored n /public. \th
euch teruton ol the oop, $product s set to euch product n products.xml, one
ulter unother.
1he return purt ol the expresson returns the product nume n $product.
Chupter l7: XML und the Cruce Dutubuse

1he next query retreves the product types lrom the /public/product_types.xml
resource:
SELECT XMLQUERY(
'for $product_type in
doc("/public/product_types.xml")/product_types/product_type
return <product_type name="{$product_type/@name}"/>'
RETURNING CONTENT
)
AS xml_product_types
FROM DUAL;
XML_PRODUCT_TYPES
------------------------------------------
<product_type name="Book"></product_type>
<product_type name="Video"></product_type>
1he loowng query retreves the products whose prce s greuter thun 20, uong wth ther
product type:
SELECT XMLQUERY(
'for $product in doc("/public/products.xml")/products/product
let $product_type :=
doc("/public/product_types.xml")//product_type[@product_type_id =
$product/@product_type_id]/@name
where $product/@price > 20
order by $product/@product_id
return <product name="{$product/@name}"
product_type="{$product_type}"/>'
RETURNING CONTENT
)
AS xml_query_results
FROM DUAL;
XML_QUERY_RESULTS
---------------------------------------------------------
<product name="Chemistry" product_type="Book"></product>
<product name="Supernova" product_type="Video"></product>
Let's breuk down the XQuery expresson n ths exumpe:
1wo bndng vurubes ure used: $product und $product_type. 1hese vurubes ure
used to store the products und product types.
1he let purt ol the expresson sets $product_type to the product type retreved lrom
$product. 1he expresson on the rght-hund sde ol the := perlorms u on usng the
product_type_id vuue stored n $product_type und $product. 1he // meuns
retreve u eements.
1he where purt retreves ony products whose prce s greuter thun 20.
1he order by purt orders the resuts by the product lD (n uscendng order by deluut).
622
Cruce Dutubuse llg SQL
1he next exumpe shows the use ol the loowng XQuery lunctons:
count(), whch counts the number ol obects pussed to t.
avg(), whch cucuutes the uveruge ol the numbers pussed to t.
integer(), whch truncutes u number und returns the nteger. 1he integer()
luncton s n the xs numespuce. (1he count() und avg() lunctons ure n the fn
numespuce, whch s uutomutcuy relerenced by the dutubuse, thereby uowng you
to omt ths numespuce when cung these lunctons.)
1he loowng exumpe returns the product type nume, the number ol products n euch
product type, und the uveruge prce ol the products n euch product type (truncuted to un nteger):
SELECT XMLQUERY(
'for $product_type in
doc("/public/product_types.xml")/product_types/product_type
let $product :=
doc("/public/products.xml")//product[@product_type_id =
$product_type/@product_type_id]
return
<product_type name="{$product_type/@name}"
num_products="{count($product)}"
average_price="{xs:integer(avg($product/@price))}"
/>'
RETURNING CONTENT
)
AS xml_query_results
FROM DUAL;
XML_QUERY_RESULTS
---------------------------------------------------------------
<product_type name="Book" num_products="2" average_price="24">
</product_type>
<product_type name="Video" num_products="1" average_price="25">
</product_type>
As you cun see lrom the resuts, there ure two books und one vdeo.
NOTf
You can rcad morc abou| |unc|on a| h||p://vvv.vJ.org/TR/xqucr,-
opcra|or. You can |nd morc n|orma|on on XMLQUERY() a| h||p://
vvv.qx.org.
Saving XMl in thc Databasc
ln ths secton, you' see how to store un XML document n the dutubuse und retreve nlormuton
lrom the stored XML.
Chupter l7: XML und the Cruce Dutubuse
623
Thc fxampIc XMl fiIc
You' see the use ol u le numed purchase_order.xml, whch s un XML le thut contuns
u purchuse order. 1hs le s contuned n the xml_files drectory, whch s creuted when you
extructed the Zp le lor ths book. ll you wunt to loow uong wth the exumpes, you shoud
copy the xml_files drectory to the C purtton on your dutubuse server (l you're usng Lnux
or Lnx, you cun copy the drectory to one ol your purttons).
NOTf
| ,ou cop, |hc xml_files drcc|or, |o a oca|on d||crcn| |rom C,
|hcn ,ou' nccd |o cd| |hc xml_schema.sql crp| (,ou' cc |h
crp| hor|,).
1he contents ol the purchase_order.xml le s us loows:
<?xml version="1.0"?>
<purchase_order>
<customer_order_id>176</customer_order_id>
<order_date>2007-05-17</order_date>
<customer_name>Best Products 456 Inc.</customer_name>
<street>10 Any Street</street>
<city>Any City</city>
<state>CA</state>
<zip>94440</zip>
<phone_number>555-121-1234</phone_number>
<products>
<product>
<product_id>1</product_id>
<name>Supernova video</name>
<quantity>5</quantity>
</product>
<product>
<product_id>2</product_id>
<name>Oracle SQL book</name>
<quantity>4</quantity>
</product>
</products>
</purchase_order>
ln the loowng sectons, you' see how to store ths XML le n the dutubuse.
ln u reu-word exumpe, the purchuse order coud be sent vu the lnternet to un onne store,
whch woud then dsputch the requested tems to the customer.
Crcating thc fxampIc XMl Schcma
l've provded un SQL*lus scrpt numed xml_schema.sql n the SQL drectory. 1he scrpt
creutes u user numed xml_user wth u pussword ol xml_password, und t creutes the tems
used n the rest ol ths chupter. Don't run ths scrpt yet.

Cruce Dutubuse ll SQL
1he scrpt contuns the loowng stutements thut creute un obect type numed t_product
(used to represent products), u nested tube type numed t_nested_table_product (used to
represent u nested tube ol products), und u tube numed purchase_order:
CREATE TYPE t_product AS OBJECT (
product_id INTEGER,
name VARCHAR2(15),
quantity INTEGER
);
/
CREATE TYPE t_nested_table_product AS TABLE OF t_product;
/
CREATE TABLE purchase_order (
purchase_order_id INTEGER CONSTRAINT purchase_order_pk PRIMARY KEY,
customer_order_id INTEGER,
order_date DATE,
customer_name VARCHAR2(25),
street VARCHAR2(15),
city VARCHAR2(15),
state VARCHAR2(2),
zip VARCHAR2(5),
phone_number VARCHAR2(12),
products t_nested_table_product,
xml_purchase_order XMLType
)
NESTED TABLE products
STORE AS nested_products;
Notce thut the xml_purchase_order coumn s ol type XMLType, whch s u but-n
Cruce dutubuse type thut uows you to store XML dutu. y deluut, un XMLType coumn stores
the XML dutu us text n u CLC (churucter urge obect).
1he xml_schema.sql scrpt uso contuns the loowng stutement thut creutes u drectory
obect numed XML_FILES_DIR:
CREATE OR REPLACE DIRECTORY XML_FILES_DIR AS 'C:\xml_files';
You' need to modly ths ne l you coped the xml_files drectory to u ocuton dllerent
lrom C. ll you need to modly ths ne, go uheud und do t now und then suve the scrpt.
1he loowng INSERT stutement (uso contuned n the scrpt) udds u row to the purchase_
order tube:
INSERT INTO purchase_order (
purchase_order_id,
xml_purchase_order
) VALUES (
1,
XMLType(
BFILENAME('XML_FILES_DIR', 'purchase_order.xml'),
NLS_CHARSET_ID('AL32UTF8')
)
);
Chupter l7: XML und the Cruce Dutubuse
62S
As you cun see, the XMLType() constructor uccepts two purumeters. 1he lrst purumeter s
u BFILE, whch s u ponter to un externu le. 1he second purumeter s the churucter set lor the
XML text n the externu le. ln the prevous INSERT, the BFILE ponts to the purchase_
order.xml le, und the churucter set s AL32L1l8, whch s stundurd L1l-8 encodng. \hen
the INSERT s run, the XML lrom the purchase_order.xml le s reud und then stored n the
dutubuse us CLC text n the xml_purchase_order coumn.
NOTf
Vhcn ,ou arc vor|ng v|h X\ |c vr||cn n ngh, ,ou
houd |,pca, uc |hc AJ2LT8 charac|cr c|. You can |nd morc
n|orma|on abou| d||crcn| charac|cr c| n |hc Cruce Dutubuse
Cobuzuton Support Cude pubhcd b, Cracc Corpora|on.
You muy huve notced the customer_order_id, order_date, customer_name,
street, city, state, zip, phone_number, und products coumns n the purchase_
order tube ure empty. 1he dutu lor these coumns cun be extructed lrom the XML stored n the
xml_purchase_order coumn. Luter n ths chupter, you' see u lL/SQL procedure thut reuds
the XML und sets the other coumns uccordngy.
Co uheud und run the xml_schema.sql scrpt us u prveged user (such us the system
user):
CONNECT system/manager
@ "E:\Oracle SQL book\sql_book\SQL\xml_schema.sql"
Alter the scrpt competes, you w be ogged n us xml_user.
Rctricving lnfurmatiun frum thc fxampIc XMl Schcma
ln ths secton, you' see how to retreve nlormuton lrom the xml_user schemu.
1he loowng exumpe retreves the row lrom the purchase_order tube:
SET LONG 1000
SET PAGESIZE 500
SELECT purchase_order_id, xml_purchase_order
FROM purchase_order;
PURCHASE_ORDER_ID
-----------------
XML_PURCHASE_ORDER
-------------------------------------------------------
1
<?xml version="1.0"?>
<purchase_order>
<customer_order_id>176</customer_order_id>
<order_date>2007-05-17</order_date>
<customer_name>Best Products 456 Inc.</customer_name>
<street>10 Any Street</street>
<city>Any City</city>
<state>CA</state>
<zip>94440</zip>
<phone_number>555-121-1234</phone_number>
<products>

Cruce Dutubuse ll SQL
<product>
<product_id>1</product_id>
<name>Supernova video</name>
<quantity>5</quantity>
</product>
<product>
<product_id>2</product_id>
<name>Oracle SQL book</name>
<quantity>4</quantity>
</product>
</products>
</purchase_order>
1he next query extructs the customer_order_id, order_date, customer_name, und
phone_number lrom the XML stored n the xml_purchase_order coumn usng the
EXTRACT() luncton:
SELECT
EXTRACT(xml_purchase_order,
'/purchase_order/customer_order_id') cust_order_id,
EXTRACT(xml_purchase_order, '/purchase_order/order_date') order_date,
EXTRACT(xml_purchase_order, '/purchase_order/customer_name') cust_name,
EXTRACT(xml_purchase_order, '/purchase_order/phone_number') phone_number
FROM purchase_order
WHERE purchase_order_id = 1;
CUST_ORDER_ID
------------------------------------------
ORDER_DATE
-----------------------------------
CUST_NAME
-----------------------------------------------------
PHONE_NUMBER
-----------------------------------------
<customer_order_id>176</customer_order_id>
<order_date>2007-05-17</order_date>
<customer_name>Best Products 456 Inc.</customer_name>
<phone_number>555-121-1234</phone_number>
1he EXTRACT() luncton returns the vuues us XMLType obects.
You cun use the EXTRACTVALUE() luncton to get the vuues us strngs. lor exumpe, the
loowng query extructs the sume vuues us strngs usng the EXTRACTVALUE() luncton:
SELECT
EXTRACTVALUE(xml_purchase_order,
'/purchase_order/customer_order_id') cust_order_id,
EXTRACTVALUE(xml_purchase_order,
'/purchase_order/order_date') order_date,
EXTRACTVALUE(xml_purchase_order,
'/purchase_order/customer_name') cust_name,
EXTRACTVALUE(xml_purchase_order,
Chupter l7: XML und the Cruce Dutubuse

'/purchase_order/phone_number') phone_number
FROM purchase_order
WHERE purchase_order_id = 1;
CUST_ORDER_ID
----------------------
ORDER_DATE
----------------------
CUST_NAME
----------------------
PHONE_NUMBER
----------------------
176
2007-05-17
Best Products 456 Inc.
555-121-1234
1he next query extructs und converts order_date to u DATE usng the TO_DATE()
luncton, notce thut the lormut lor the dute us stored n the XML s supped usng the second
purumeter to TO_DATE() und thut TO_DATE() returns the dute n the deluut dute lormut used
by the dutubuse (DD-MON-YY):
SELECT
TO_DATE(
EXTRACTVALUE(xml_purchase_order, '/purchase_order/order_date'),
'YYYY-MM-DD'
) AS ord_date
FROM purchase_order
WHERE purchase_order_id = 1;
ORD_DATE
---------
17-MAY-07
1he loowng query retreves u the products lrom xml_purchase_order us XML usng
EXTRACT(), notce the use ol // to get u the products:
SELECT
EXTRACT(xml_purchase_order, '/purchase_order//products') xml_products
FROM purchase_order
WHERE purchase_order_id = 1;
XML_PRODUCTS
--------------------------------
<products>
<product>
<product_id>1</product_id>
<name>Supernova video</name>
<quantity>5</quantity>
</product>
<product>

Cruce Dutubuse ll SQL
<product_id>2</product_id>
<name>Oracle SQL book</name>
<quantity>4</quantity>
</product>
</products>
1he next query retreves product r2 lrom xml_purchase_order, notce product[2]
returns product r2:
SELECT
EXTRACT(
xml_purchase_order,
'/purchase_order/products/product[2]'
) xml_product
FROM purchase_order
WHERE purchase_order_id = 1;
XML_PRODUCT
---------------------------------
<product>
<product_id>2</product_id>
<product>Oracle SQL book</name>
<quantity>4</quantity>
</product>
1he loowng query retreves the Supernovu vdeo product lrom xml_purchase_order,
notce thut the nume ol the product to retreve s puced nsde squure bruckets:
SELECT
EXTRACT(
xml_purchase_order,
'/purchase_order/products/product[name="Supernova video"]'
) xml_product
FROM purchase_order
WHERE purchase_order_id = 1;
XML_PRODUCT
------------------------------
<product>
<product_id>1</product_id>
<name>Supernova video</name>
<quantity>5</quantity>
</product>
You use the EXISTSNODE() luncton to check l un XML eement exsts. EXISTSNODE()
returns l l the eement exsts, otherwse, t returns 0. lor exumpe, the loowng query returns
the strng 'Exists' becuuse product rl exsts:
SELECT 'Exists' AS "EXISTS"
FROM purchase_order
WHERE purchase_order_id = 1
AND EXISTSNODE(
Chupter l7: XML und the Cruce Dutubuse

xml_purchase_order,
'/purchase_order/products/product[product_id=1]'
) = 1;
EXISTS
------
Exists
1he next query returns no rows becuuse product r3 does not exst:
SELECT 'Exists'
FROM purchase_order
WHERE purchase_order_id = 1
AND EXISTSNODE(
xml_purchase_order,
'/purchase_order/products/product[product_id=3]'
) = 1;
no rows selected
1he loowng query retreves the products us u vurruy ol XMLType obects usng the
XMLSEQUENCE() luncton, notce the use ol product.* to retreve u the products und
ther XML eements:
SELECT product.*
FROM TABLE(
SELECT
XMLSEQUENCE(EXTRACT(xml_purchase_order, '/purchase_order//product'))
FROM purchase_order
WHERE purchase_order_id = 1
) product;
COLUMN_VALUE
------------------------------
<product>
<product_id>1</product_id>
<name>Supernova video</name>
<quantity>5</quantity>
</product>
<product>
<product_id>2</product_id>
<name>Oracle SQL book</name>
<quantity>4</quantity>
</product>
1he next query retreves the product_id, name, und quantity lor the products us strngs
usng the EXTRACTVALUE() luncton:
SELECT
EXTRACTVALUE(product.COLUMN_VALUE, '/product/product_id') AS product_id,
EXTRACTVALUE(product.COLUMN_VALUE, '/product/name') AS name,
630
Cruce Dutubuse ll SQL
EXTRACTVALUE(product.COLUMN_VALUE, '/product/quantity') AS quantity
FROM TABLE(
SELECT
XMLSEQUENCE(EXTRACT(xml_purchase_order, '/purchase_order//product'))
FROM purchase_order
WHERE purchase_order_id = 1
) product;
PRODUCT_ID
--------------
PRODUCT
---------------
QUANTITY
---------------
1
Supernova video
5
2
Oracle SQL book
4
Updating lnfurmatiun in thc fxampIc XMl Schcma
1he customer_order_id, order_date, customer_name, street, city, state, zip,
phone_number, und products coumns n the purchase_order tube ure empty. 1he dutu
lor these coumns cun be extructed lrom the XML stored n the xml_purchase_order coumn.
ln ths secton, you' u lL/SQL procedure numed update_purchase_order() thut reuds the
XML und sets the other coumns uccordngy.
1he most compex uspect ol update_purchase_order() s the process ol reudng
the products lrom the XML und storng them n the products nested tube coumn ol the
purchase_order tube. ln ths procedure, u cursor s used to reud the products lrom the XML,
then the XML s converted to strngs usng EXTRACTVALUE(), und the strngs ure stored n u
nested tube.
1he loowng stutement (contuned n the xml_schema.sql scrpt) creutes the update_
purchase_order() procedure:
CREATE PROCEDURE update_purchase_order(
p_purchase_order_id IN purchase_order.purchase_order_id%TYPE
) AS
v_count INTEGER := 1;
-- declare a nested table to store products
v_nested_table_products t_nested_table_product :=
t_nested_table_product();
-- declare a type to represent a product record
TYPE t_product_record IS RECORD (
product_id INTEGER,
name VARCHAR2(15),
quantity INTEGER
);
Chupter l7: XML und the Cruce Dutubuse

-- declare a REF CURSOR type to point to product records


TYPE t_product_cursor IS REF CURSOR RETURN t_product_record;
-- declare a cursor
v_product_cursor t_product_cursor;
-- declare a variable to store a product record
v_product t_product_record;
BEGIN
-- open v_product_cursor to read the product_id, name, and quantity for
-- each product stored in the XML of the xml_purchase_order column
-- in the purchase_order table
OPEN v_product_cursor FOR
SELECT
EXTRACTVALUE(product.COLUMN_VALUE, '/product/product_id')
AS product_id,
EXTRACTVALUE(product.COLUMN_VALUE, '/product/name') AS name,
EXTRACTVALUE(product.COLUMN_VALUE, '/product/quantity') AS quantity
FROM TABLE(
SELECT
XMLSEQUENCE(EXTRACT(xml_purchase_order, '/purchase_order//product'))
FROM purchase_order
WHERE purchase_order_id = p_purchase_order_id
) product;
-- loop over the contents of v_product_cursor
LOOP
-- fetch the product records from v_product_cursor and exit when there
-- are no more records found
FETCH v_product_cursor INTO v_product;
EXIT WHEN v_product_cursor%NOTFOUND;
-- extend v_nested_table_products so that a product can be stored in it
v_nested_table_products.EXTEND;
-- create a new product and store it in v_nested_table_products
v_nested_table_products(v_count) :=
t_product(v_product.product_id, v_product.name, v_product.quantity);
-- display the new product stored in v_nested_table_products
DBMS_OUTPUT.PUT_LINE('product_id = ' ||
v_nested_table_products(v_count).product_id);
DBMS_OUTPUT.PUT_LINE('name = ' ||
v_nested_table_products(v_count).name);
DBMS_OUTPUT.PUT_LINE('quantity = ' ||
v_nested_table_products(v_count).quantity);
-- increment v_count ready for the next iteration of the loop
v_count := v_count + 1;
END LOOP;
-- close v_product_cursor

Cruce Dutubuse ll SQL
CLOSE v_product_cursor;
-- update the purchase_order table using the values extracted from the
-- XML stored in the xml_purchase_order column (the products nested
-- table is set to v_nested_table_products already populated by the
-- previous loop)
UPDATE purchase_order
SET
customer_order_id =
EXTRACTVALUE(xml_purchase_order,
'/purchase_order/customer_order_id'),
order_date =
TO_DATE(EXTRACTVALUE(xml_purchase_order,
'/purchase_order/order_date'), 'YYYY-MM-DD'),
customer_name =
EXTRACTVALUE(xml_purchase_order, '/purchase_order/customer_name'),
street =
EXTRACTVALUE(xml_purchase_order, '/purchase_order/street'),
city =
EXTRACTVALUE(xml_purchase_order, '/purchase_order/city'),
state =
EXTRACTVALUE(xml_purchase_order, '/purchase_order/state'),
zip =
EXTRACTVALUE(xml_purchase_order, '/purchase_order/zip'),
phone_number =
EXTRACTVALUE(xml_purchase_order, '/purchase_order/phone_number'),
products = v_nested_table_products
WHERE purchase_order_id = p_purchase_order_id;
-- commit the transaction
COMMIT;
END update_purchase_order;
/
1he loowng exumpe sets the server output on und cus update_purchase_order() to
updute purchuse order rl:
SET SERVEROUTPUT ON
CALL update_purchase_order(1);
product_id = 1
name = Supernova video
quantity = 5
product_id = 2
name = Oracle SQL book
quantity = 4
1he loowng query retreves the coumns lrom purchuse order rl:
SELECT purchase_order_id, customer_order_id, order_date, customer_name,
street, city, state, zip, phone_number, products
FROM purchase_order
Chupter l7: XML und the Cruce Dutubuse

WHERE purchase_order_id = 1;
PURCHASE_ORDER_ID CUSTOMER_ORDER_ID ORDER_DAT CUSTOMER_NAME
----------------- ----------------- --------- ----------------------
STREET CITY ST ZIP PHONE_NUMBER
--------------- --------------- -- ----- ------------
PRODUCTS(PRODUCT_ID, NAME, QUANTITY)
------------------------------------
1 176 17-MAY-07 Best Products 456 Inc.
10 Any Street Any City CA 94440 555-121-1234
T_NESTED_TABLE_PRODUCT(
T_PRODUCT(1, 'Supernova video', 5),
T_PRODUCT(2, 'Oracle SQL book', 4)
)
1he products nested tube contuns the sume dutu us stored n the XML product eements n
the xml_purchase_order coumn. l've udded some ne breuks to sepurute the products n the
exumpe's resuts to muke them euser to see.

ln ths chupter, you huve eurned


How to generute XML lrom reutonu dutu.
How to suve XML n the dutubuse und subsequenty reud thut XML to updute reutonu
coumns.
1hs short chupter hus burey scrutched the surluce ol the rch XML lunctonuty uvuube n
the Cruce dutubuse. You cun lnd more nlormuton n the Cracc X\ Dcvcopcr' K| und the
Cracc X\ D Dcvcopcr' Cudc, both pubshed by Cruce Corporuton.
Apurt lrom the lnu uppendx, ths s the end ol ths book. l hope you've lound the book
nlormutve und uselu, und thut l've hed your nterest!
This page intentionally left blank

Cruce Dutu 1ypes


635
636
Cruce Dutubuse llg SQL
hs uppendx contuns two tubes documentng the dutu types thut ure uvuube n
Cruce SQL und thut muy be used to delne coumns n u tube, uong wth the
uddtonu types supported by Cruce lL/SQL.
OracIc SQl Typcs
1ube A-l shows the Cruce SQL types.

Typc Dcscriptiun
CHAR[(length [BYTE | CHAR])]
l
lxed-ength churucter dutu ol length bytes or churucters und pudded wth trung
spuces. Muxmum ength s 2,000 bytes.
VARCHAR2(length [BYTE | CHAR])
l
Vurube-ength churucter dutu ol up to length bytes or churucters. Muxmum
ength s 4,000 bytes.
NCHAR[(length)] lxed-ength Lncode churucter dutu ol length churucters. Number ol bytes stored
s 2 mutped by length lor ALl6L1ll6 encodng und 3 mutped by length
lor L1l8 encodng. Muxmum ength s 2,000 bytes.
NVARCHAR2(length) Vurube-ength Lncode churucter dutu ol length churucters. Number ol bytes
stored s 2 mutped by length lor ALl6L1ll6 encodng und 3 mutped by
length lor L1l8 encodng. Muxmum ength s 4,000 bytes.
BINARY_FLOAT lntroduced n Cruce Dutubuse l0g, stores u snge-precson 32-bt loutng-pont
number. Cperutons nvovng BINARY_FLOAT ure typcuy perlormed luster
thun operutons usng NUMBER vuues. BINARY_FLOAT requres 5 bytes ol
storuge spuce.
BINARY_DOUBLE lntroduced n Cruce Dutubuse l0g, stores u doube-precson 64-bt loutng-pont
number. Cperutons nvovng BINARY_DOUBLE ure typcuy perlormed luster
thun operutons usng NUMBER vuues. BINARY_DOUBLE requres 9 bytes ol
storuge spuce.
NUMBER(precision, scale) und
NUMERIC(precision, scale)
Vurube-ength number, precision s the muxmum number ol dgts (elt und
rght ol u decmu pont, l used) thut muy be used lor the number. 1he muxmum
precson supported s 38, scale s the muxmum number ol dgts to the rght
ol u decmu pont (l used). ll nether precision nor scale s specled, then u
number wth up to u precson und scue ol 38 dgts muy be supped (meunng you
cun suppy u number wth up to 38 dgts, und uny ol those 38 dgts muy be rght
or elt ol the decmu pont).
DEC und DECIMAL Subtype ol NUMBER. A lxed-pont decmu number wth up to 38 dgts ol decmu
precson.
DOUBLE PRECISION und FLOAT Subtype ol NUMBER. A loutng-pont number wth up to 38 dgts ol precson.
REAL
Subtype ol NUMBER. A loutng-pont number wth up to l8 dgts ol precson.
INT, INTEGER, und SMALLINT Subtype ol NUMBER. An nteger wth up to 38 dgts ol decmu precson.
DATE
Dute und tme wth the century, u lour dgts ol yeur, month, duy, hour (n 24-
hour lormut), mnute, und second. Muy be used to store u dute und tme between
}unuury l, 47l2 .C. und December 3l, 47l2 A.D. Deluut lormut s specled by
the NLS_DATE_FORMAT dutubuse purumeter (lor exumpe: DD-MON-RR).
INTERVAL YEAR[(years_precision)]
TO MONTH
1me ntervu meusured n yeurs und months, years_precision specles the
precson lor the yeurs, whch muy be un nteger lrom 0 to 9 (deluut s 2). Cun be
used to represent u postve or negutve tme ntervu.
TABlf A-1 Cracc S T,pc
Appendx: Cruce Dutu 1ypes
637
Typc Dcscriptiun
INTERVAL DAY[(days_precision)] TO
SECOND[(seconds_precision)]
1me ntervu meusured n duys und seconds, days_precision specles the
precson lor the duys, whch s un nteger lrom 0 to 9 (deluut s 2), seconds_
precision specles the precson lor the lructonu purt ol the seconds, whch s
un nteger lrom 0 to 9 (deluut s 6). Cun be used to represent u postve or negutve
tme ntervu.
TIMESTAMP[(seconds_precision)] Dute und tme wth the century, u lour dgts ol yeur, month, duy, hour (n 24-hour
lormut), mnute, und second, seconds_precision specles the number ol dgts
lor the lructonu purt ol the seconds, whch cun be un nteger lrom 0 to 9 (deluut
s 6). Deluut lormut s specled by the NLS_TIMESTAMP_FORMAT dutubuse
purumeter.
TIMESTAMP[(seconds_precision)] WITH
TIME ZONE
Lxtends TIMESTAMP to store u tme zone. 1he tme zone cun be un ollset lrom
L1C, such us -8:0, or u regon nume, such us US/Pacific or PST. Deluut
lormut s specled by the NLS_TIMESTAMP_TZ_FORMAT dutubuse purumeter.
TIMESTAMP[(seconds_precision)] WITH
LOCAL TIME ZONE
Lxtends TIMESTAMP to convert u supped dutetme to the ocu tme zone set lor
the dutubuse. 1he process ol converson s known us norma2ng the dutetme.
Deluut lormut s specled by the NLS_TIMESTAMP_FORMAT dutubuse purumeter.
CLOB Vurube-ength snge-byte churucter dutu ol up to l28 terubytes.
NCLOB Vurube-ength Lncode nutonu churucter set dutu ol up to l28 terubytes.
BLOB Vurube-ength bnury dutu ol up to l28 terubytes.
BFILE lonter to un externu le. 1he externu le s not stored n the dutubuse.
LONG Vurube-ength churucter dutu ol up to 2 ggubytes. Superseded by the CLOB und
NCLOB types, but supported lor buckwurds computbty.
RAW(length) Vurube-ength bnury dutu ol up to length bytes. Muxmum ength s 2,000
bytes. Superseded by the BLOB type, but supported lor buckwurds computbty.
LONG RAW Vurube-ength bnury dutu ol up to 2 ggubytes. Superseded by the BLOB type but
supported lor buckwurds computbty.
ROWID Hexudecmu strng used to represent u row uddress.
UROWID[(length)] Hexudecmu strng representng the ogcu uddress ol u row ol un ndex-orgunzed
tube, length specles the number ol bytes. Muxmum ength s 4,000 bytes (uso
the deluut ength l none s specled).
REF object_type Relerence to un obect type. Smur to u ponter n the C++ progrummng unguuge.
VARRAY Vurube-ength urruy. 1hs s u composte type und stores un ordered set ol
eements.
NESTED TABLE Nested tube. 1hs s u composte type und stores un unordered set ol eements.
XMLType Stores XML dutu.
User defined object type You cun delne your own obect type und creute obects ol thut type. See Chupter
l2 lor detus.
l
1he BYTE und CHAR keywords work ony wth Cruce Dutubuse 9 und ubove. ll nether BYTE nor CHAR s specled, the
deluut s BYTE.
TABlf A-1 Cracc S T,pc (contnued)
638
Cruce Dutubuse llg SQL
Typc Dcscriptiun
BOOLEAN
ooeun vuue (TRUE, FALSE, or NULL).
BINARY_INTEGER
lnteger between 2
3l
(2,l47,483,648) und 2
3l
(2,l47,483,648).
NATURAL
Subtype ol BINARY_INTEGER. A non-negutve nteger.
NATURALN
Subtype ol BINARY_INTEGER. A non-negutve nteger (cunnot
be NULL).
POSITIVE
Subtype ol BINARY_INTEGER. A postve nteger.
POSITIVEN
Subtype ol BINARY_INTEGER. A postve nteger (cunnot be NULL).
SIGNTYPE
Subtype ol BINARY_INTEGER. An nteger set to l, 0, or l.
PLS_INTEGER
lnteger between 2
3l
(2,l47,483,648) und 2
3l
(2,l47,483,648).
ldentcu to BINARY_INTEGER.
SIMPLE_INTEGER
New lor Cruce Dutubuse llg, SIMPLE_INTEGER s u subtype ol
BINARY_INTEGER. SIMPLE_INTEGER cun store the sume runge ol
vuues us BINARY_INTEGER, except lor NULL vuues, whch cunnot
be stored n u SIMPLE_INTEGER. Aso, urthmetc overlow does not
cuuse un error when usng SIMPLE_INTEGER vuues, nsteud, the
resut s smpy truncuted.
STRING
Sume us VARCHAR2.
RECORD
Composte ol u group ol other types. Smur to u structure n the C++
progrummng unguuge.
REF CURSOR
lonter to u set ol rows.
TABlf A-2 Cracc /S T,pc
OracIc Pl/SQl Typcs
Cruce lL/SQL supports u the types prevousy shown n 1ube A-l, pus the loowng uddtonu
Cruce lL/SQL speclc types shown n 1ube A-2.
SymbuIs
(mnus), 3l
r (pound), l07
% (percent), 404l
%1YlL, 342, 346
( ) (purentheses), 34, l68
* (ustersk)
n urthmetc, 3l
coumn retrevu, 29
customers tube, l5
metuchuructers, ll0
(lorwurd sush)
n urthmetc, 3l
edtng SQL stutements, 6566
lL/SQL stutements, 34l
SQL drectory puths, l0
\ (buckwurd sush), l0
:new uttrbute, 524525
, (semcoon), 6, 34l
: (queston murk), 564
!= (not equu), 3839
@ filename, 67
_ (underscore), 404l
]] (concutenuton operutor), 34
+ (pus)
n urthmetc, 3l
outer ons, 5l55
< (ess thun)
compurng obect vuues, 393
non-equons, 50
vuue compurson, 3839
<= (ess thun or equu)
compurng obect vuues, 393
non-equons, 50
vuue compurson, 3839
<> (not equu)
ANSl nested tube support,
464465
compurng obect vuues,
392394
vuue compurson, 3839
= (equu)
ANSl nested tube support,
464465
compurng obect vuues,
392393
equons, 50
vuue compurson, 3839
> (greuter thun)
compurng obect vuues,
393394
non-equons, 50
vuue compurson, 3839
>= (greuter thun or equu)
compurng obect vuues, 393
non-equons, 50
vuue compurson, 3839
" (quotes), 34, 254
A
AS( ), 98, l00
ACCLl1, 7879, 808l
ACCLSS_lN1C_NLLL, 354
AClD (utomc, consstent, souted
und durube) trunsucton
propertes, 265266
ACCS( ), 98
ADDM (Automutc Dutubuse
Dugnostc Montor), 60060l
lndcx
ADD_MCN1HS( ), l42l43
udvunced queres. queres,
udvunced
uggregute lunctons
delned, 90
groupng rows, l20l27
mutpe n llVC1, 247248
RL1LRNlNC, 255256
wth RCLLLl, 207
types ol, ll7l20
ugorthms, LC dutu encrypton, 526
uuses
coumns, 3435
tube, 4748
ALL, 3839, l75
AL1LR
delned, 3
lNDLX, 324
SLQLLNCL, 320
1ALL, 302306
Amercun Nutonu Stundurds
lnsttute (ANSl), 464472
unuytc lunctons
delned, 2l62l7
llRS1 und LAS1 lunctons, 233
hypothetcu runk und
dstrbuton lunctons, 235
nverse percente lunctons,
224225
LAC( ) und LLAD( ), 232233
neur regresson lunctons,
233235
runkng lunctons, 2l7224
reportng lunctons, 230232
wndow lunctons, 225230
639

Cruce Dutubuse ll SQL


AND, 43, 238
ANSl (Amercun Nutonu Stundurds
lnsttute), 47, 464472
ANY
uccessng u ces usng,
238239
mutpe-row subqueres, l74
vuue compurson, 3839
AllLND, 6566
AllLND( )
dutu to CLCs, 506507
delned, 483, 485
urthmetc, 3l34
urruys, ussocutve, 428
ussocutve, 462
urruys, vurruy. vurruys
ASCll( ), 9l92
ASlN( ), 98
ussocutve urruys, 428, 462
ustersk (*). * (ustersk)
A1AN( ), 98
A1AN2( ), 99
utomc trunsuctons, 265
uttrbutes
:new, 524525
OracleDataSource,
540542
XMLA11RlL1LS( ), 608
uudtng
overvew, 295297
usng trggers, 369374
uuto-commt mode, 552553
Automutc Dutubuse Dugnostc
Montor (ADDM), 60060l
uutomutcuy generuted SQL
stutements, 86
uveruges
centered, 228229
movng, 227228
AVC( ), ll7ll8

-tree ndexes, 32l322


buckwurd sush (\), l0
buse tubes, 325
BasicExample1.java, 556562
BasicExample2.java, 565567
BasicExample3.java, 575577
L1\LLN
ce runge uccess usng, 238
compurng obect vuues, 393
delned, 39
non-equons, 505l
overvew, 4243
llLLs (bnury llLL types)
copyng dutu lrom nto CLCs
und LCs, 5l7520
delned, 477478
llLLCLCSL( ) und
llLLCLCSLALL( ), 489
llLLLXlS1S( ), 490
llLLCL1NAML( ), 490
llLLlSClLN( ), 49049l
llLLClLN( ), 49l
LCADLClRCMllLL( ), 497
LCADCLClRCMllLL( ),
497498
LCADlRCMllLL( ), 496
usng n SQL, 48l482
bnury LCs (LCs). LCs
(bnury LCs)
lNARY_DCLLL, l3, 2325
lNARY_lLCA1, l3, 2325
bnd vurubes, 58859l
bnds, 539
bt vectors, 2l2
l1AND( ), 99
btmup ndexes, 32l, 324325
LCs (bnury LCs)
compresson, 529
copyng dutu lrom llLL nto,
5l7520
copyng dutu lrom le nto,
5l25l5
copyng dutu lrom nto les,
5l55l7
delned, 477478
encrypton, 526528
LCADLClRCMllLL( ), 497
reudng dutu lrom, 504506
usng n SQL, 47848l
bock structure, 340342
body, obect type, 38l382
body, puckuge, 365367
brunch emnuton, 20l202
RLAK CN, 8385
1l1LL, 8283
buckets, 223

CACHL n sequences, 3l9


cuchng LC dutu, 526
cucuutons, numerc, 98l02
cucuutons wth MCDLL.
MCDLL
cung lL/SQL lunctons, 364,
367368
cung lL/SQL procedures, 360
36l, 367368
CARDlNALl1Y( ), 469
Curtesun products, 4849
CASL expressons
udvunced queres, l93l96
vs. mutpe queres, 583
usng wth CRCLllNC( ),
2092l0
CASL_NC1_lCLND, 354
CAS1( ), l08l09, 443444
CLlL( ), 99, l00
ces
uccessng u usng ANY und lS
ANY, 238239
lCR oops, 24024l
postonu und symboc
notuton, 237238
runge uccess usng L1\LLN
und AND, 238
updutng exstng, 243244
centered uveruge, 228229
centru pun tubes, 593
century lormuttng, l33
CHANCL, 6566
chungng tube contents. tube
contents, chungng
CHAR( ), l3
churucter lunctons
delned, 90
types ol, 9098
churucter LCs (CLCs). CLCs
(churucter LCs)
churucters
vurube delnton, 76
XML les wrtten n Lngsh, 625
CHLCK, 306, 307
CHLCK Cl1lCN, 306, 329
chd nodes, l97
chd tubes, 257258
CHR( ), 9l92
lndex

chunks ol dutu, 492


cusses
computbe Cruce dutubuse
types, 568
obect types us, 380
oruce.dbc puckuge, 573
CLASSlA1H envronment vurube,
534535
CLLAR, 707l
CLLAR, 73
CLCs (churucter LCs)
uppendng dutu to, 506507
compurng dutu, 507508
compresson, 529
copyng dutu lrom, 508509
copyng dutu lrom llLL nto,
5l7520
copyng dutu lrom le nto,
5l25l5
copyng dutu lrom nto les,
5l55l7
delned, 477478
encrypton, 526528
erusng dutu lrom, 5l0
mpct converson, 523524
LCADCLClRCMllLL( ),
497498
reudng dutu lrom, 504506
seurchng dutu, 5l05ll
temporury, 5095l0
usng n SQL, 47848l
wrtng to, 506
CLCSL( ), 483, 485
cosed operutons, 23
cosng
cursors, 347
}DC obects, 554556
ResultSet obect, 546547
Codd, L. l., 2, 3
CCLLLC1( ), 47l472
CCLLLC1lCN_lS_NLLL, 354
coectons, 427473
ANSl nested tube support,
464472
ussocutve urruys, 462
compurng nested tube contents
wth mup method, 440442
convertng types wth CAS1( ),
443444
CCLN1( ), 44845l
delnng coumn wth type, 430
DLLL1L( ), 45l452
eement type szng, 463
LXlS1S( ), 452453
LX1LND( ), 453
llRS1( ), 454
generutng XML lor, 607608
ncreusng eements n
vurruy, 463
nlormuton retrevu, 43l433
ntroducton, 428429
LAS1( ), 454455
modlyng eements, 438440
muteve, 45846l
nested tube's storuge tube
tubespuce, 463464
NLX1( ), 455456
Cruce dutubuse l0g
enhuncements, 46l462
n lL/SQL, 444448
popuutng wth eements,
434435
lRlCR( ), 456457
retrevng eements lrom,
435436
summury, 473
1ALL( ), 436438
1RlM( ), 457458
types, 429430
vurruys n temporury tubes, 463
XMLACC( ), 6096l2
coumns
uccessng usng MCDLL cuuse,
236237
uddng/modlyng/removng,
303306
uuses, 3435
n urthmetc, 3234
chungng tube contents. Scc
tube contents, chungng
combnng output, 35
comments, 3l33l4
construnt nlormuton retrevu,
3ll3l2
decurng vurubes to store
vuues, 346
delned, 2
delnng wth coecton type, 430
encryptng LC dutu, 528
CRCLllNC( ), 2092ll
nlormuton retrevu on ndexes,
323324
ons wth luy quuled
relerences, 582
LCNC und LCNC RA\ types,
52l522
mutpe-coumn
subqueres, l75
obects, 383386
pvotng on mutpe, 246247
pun tube, 593
reudng vuues lrom
ResultSet obect, 544546
retrevng u, 29
n RCLLLl cuuse, 205207
SQL*lus, ceurng lormuts, 73
SQL*lus, lormuttng, 7072
substtutng numes usng
vurubes, 7677
LNllVC1, 248249
usng mutpe n group, l22
combnng lunctons, 98
commund ne SQL*lus sturtup, 6
communds
coumn lormuttng, 7072
delned vurubes, 7779
edtng SQL stutements, 6566
HLLl, 8586
suvng/retrevng/runnng les,
6670
SL1 LlNLSlZL, 73
SL1 lACLSlZL, 7273
smpe reportng, 7985
comments
n tubes, 3l33l4
XML, 6l4
CCMMl1
uuto-commt mode, 552553
delned, 4
trunsuctons, 262263
Communca|on o| |hc AC\, 2
CCMlARL( )
dutu n two CLCs, 507508
delned, 483, 486487
compurng vuues
delned, 3739
tube obects, 392394
compex vews, 332333
compresson, LC, 529
CCMlL1L, 8385

Cruce Dutubuse ll SQL


computer conlguruton lor runnng
SQL usng }uvu, 533535
computng subtotus, 8385
concutenuton
combnng coumn output, 35
CCNCA1( ), 9l92
XMLCCNCA1( ), 6l3
concutenuton operutor (]]), 34
concurrent trunsuctons, 266
condtonu ogc, 342343
condtons n herurchcu queres,
202203
condtons, trgger, 369
conlgurng computer lor runnng
SQL usng }uvu, 533535
CCNNLC1 Y, l98
connectvty, dutubuse, 537542
consstent trunsuctons, 265
construned cursors, 34535l
construnts
creutng vews wth, 329330
enlorcng, 257258
gettng nlormuton on vew,
33l332
tube, 3063l2
constructors
coumn obects, 384
obect tubes, 386
user-delned, 4l8422
CCN1LN1
pursng XML expressons, 6l3
XMLSLRlALlZL( ), 6l6
contents, chungng tube. tube
contents, chungng
converson lunctons, 90, l02l09
convertng dutetme, l3ll39, l50
CCNVLR11CLC( ), 483
CCNVLR11CCLC( ), 483
Coordnuted Lnversu 1me (L1C),
l46l47
CClY( )
copyng dutu lrom CLCs,
508509
delned, 483
LC methods, 487
copyng LC dutu
uppendng dutu to CLCs,
506507
lrom llLL nto CLCs und
LCs, 5l7520
lrom CLCs und LCs nto
les, 5l55l7
lrom le nto CLCs und
LCs, 5l25l5
copyng rows, 254
correuted subqueres, l68,
l75l79
CCS( ), 99
CCSH( ), 99
cost-bused optmzuton, 59l598
CCLN1( ), ll7ll9, 44845l
CRLA1L, 3, lll2
CRLA1L lRCCLDLRL, 2526
CRLA1L SYNCNNYM, 287288
CRLA1L LSLR, 276277
CRLA1L1LMlCRARY( ), 483, 488
cross ons, 6l
CLL
delned, 207208
vs. CRCLllNC SL1S, 2l2, 588
CRCLllNC( ) wth, 2l02ll
usng wth unuytc lunctons,
22l223
CLML_DlS1( ), 2l8, 223
cumuutve sums, 225227
CLRRLN1_DA1L( ), l49
CLRRLN1_1lMLS1AMl, l55l56
CLRRLN1V( ), 239240
currval, 3l7, 376
CLRSCR_ALRLADY_ClLN, 354
cursors
lCR oops und, 349350
ClLN-lCR stutement, 35035l
overvew, 345346
product_cursor.sq exumpe,
348349
progrummng steps, 346348
unconstruned, 352353
customer_id, l4, l7l8
customers tube, l4l5

Dutu Contro Lunguuge (DCL)


stutements, 4
Dutu Delnton Lunguuge (DDL)
stutements
delned, 3, ll20
runnng SQL usng }uvu, 553
dutu, LC
uppendng to CLC, 506507
CLCs und LCs n SQL,
47848l
compurng n CLCs, 507508
compresson, 529
copyng. copyng LC dutu
delned, 478
encrypton, 525528
erusng lrom CLC, 5l0
reudng lrom CLCs und
LCs, 504506
removng dupcute, 529
seurchng n CLC, 5l05ll
Dutu Munpuuton Lunguuge (DML)
stutements. DML (Dutu
Munpuuton Lunguuge)
stutements
dutu sources, 539542
dutu types. types
dutubuse munugement systems, 23
dutubuse obects, 379426
coumn, 383386
compurng vuues, 392394
creutng types, 38l382
delete_product(), 40040l
display_product(),
396397
generuzed nvocuton,
423425
generutng XML lor, 607
get_product(), 398399
get_product_ref(), 400
get_products(), 395396
insert_product(), 397
ntroducton, 380
lS Cl( ), 4084l2
}DC Statement, 542543
urge. LCs (urge obects)
NC1 lNS1AN1lALL types,
4l64l8
ClDs und relerences, 390392
OracleDataSource, 540542
overrdng methods, 422423
n lL/SQL, 394395
product_lifecycle(),
40l402
product_lifecycle2(),
402403
ResultSet, 543547
subtype n puce ol supertype,
405408
summury, 425426
SYS_1YlLlD( ), 4l6
tubes, 386389
1RLA1( ), 4l24l6
lndex

type nhertunce, 403405


update_product(), 399
update_product_
price(), 398
user-delned constructors,
4l8422
usng DLSCRlL to get type
nlormuton, 382383
wruppers, 55l552
dutubuse tube nlormuton retrevu,
276l
u coumns, 29
urthmetc, 3l34
Curtesun products, 4849
coumn uuses, 3435
concutenuton, 35
dstnct row dspuy, 37
on condtons und types, 50
ons usng SQL/92 syntux,
566l
non-equons, 505l
nu vuues, 3537
operutor precedence, 44
outer ons, 5l55
row dentlers, 30
row numbers, 303l
SLLLC1 stutements usng
mutpe tubes, 4950
SLLLC1 stutements usng snge
tube, 2829
SLLLC1 stutements usng two
tubes, 4547
sel ons, 5556
sortng rows, 4445
SQL operutors, 3943
summury, 6l
tube uuses, 4748
tubes und coumns n tubes,
302303
vuue compurson, 3739
\HLRL, 29
dutubuses
common types, l2l3
creutng users, lll2
ntegrty, 256258
openng connecton, 537542
tubes. tubes
tme zones, l47l49
trunsuctons, 262269, 552553
DA1L, l3
dute urthmetc, 3l32
dute ol brth (dob), l5
dutetme, l30l66
convertng, l3ll39
deluut lormut, l39l40
lunctons, l42l46
storng/retrevng, l30l3l
summury, l66
tme ntervus, l59l65
tme zones, l46l50
tmestump lunctons, l54l59
tmestumps, l50l54
two-dgt yeurs, l40l42
duys
dutetme lunctons, l43l45
deluut lormut, l30
lormut purumeters, l34
lN1LRVAL DAY 1C SLCCND,
l62l64
DCL (Dutu Contro Lunguuge)
stutements, 4
DD, l30
DDL (Dutu Delnton Lunguuge)
stutements
delned, 3, ll20
runnng SQL usng }uvu, 553
decurutons, cursor, 346
DLCCDL( ), l9ll93
deluut dutetme lormut, l39l40
deluut edtors, 69
deluut ockng, 266267
deluut roes, 294
deluut vuues, 258259, 306
delerred construnts, 3l0
DLllNL, 7778
delned vurubes
delned, 74, 7779
n scrpts, 8l
delnton churucters, 76
delntons, vew, 33033l
DLL, 6566
DLLL1L( ), 449, 45l452
DLLL1L
delned, 3
}DC, 548
removng rows, 2223, 256
stutements contunng
subqueres, l80l8l
delete_product(), 395,
40040l
DLNSL RANK( ), 2l7223
DLRLl( ), 39l392
DLSCRlL
uddng rows, 20
coecton nlormuton retrevu,
43l433
obect type nlormuton,
382383
row dentlers, 30
tube nlormuton retrevu, 302
vewng tube structure, 6465
description, l7
dmensons, current vuues, 239240
drectory obects
usng llLLs, 48l
wuets, 525526
drectory puths, l0
drty reuds, 268
dsubng construnts, 309
dsubng trggers, 374
dspuyng dstnct rows, 37
display_product(), 394,
396397
DlS1lNC1
delned, 37
vs. LXlS1S, 587
dstrbuton, 235
DML (Dutu Munpuuton Lunguuge)
stutements
chungng tube contents.
tube contents, chungng
delned, 3
perlormng wth vews, 328329
trggers, 369374
dob (dute ol brth), l5
DCCLMLN1, 6l3, 6l6
drvers, }DC
regsterng, 537
types ol, 535536
DRCl, 3
DRCl 1ALL, 86
DRCl LSLR, 278
droppng
coumns, 306
construnts, 309
ndexes, 324
puckuges, 368
lL/SQL lunctons, 365
procedures, 362
roes, 295
sequences, 320
tubes, 3l4
trggers, 374
vews, 334
dual tube, 32
dupcute LC dutu, 529

Cruce Dutubuse ll SQL


dupcute rows, 2l52l6
dupcute vuues, 356
DLl_VAL_CN_lNDLX, 354, 356
durube trunsuctons, 265

LDl1, 67
edtng SQL stutements, 7, 6566
eements
uddng to coecton, 453
countng, 44845l
deetng, 45l452
exstng, 452453
gettng lrst, 454
gettng ust, 454455
ncreusng n vurruy, 463
modlyng n coectons,
438440
popuutng coectons,
434435
removng lrom coecton,
457458
retrevng lrom coectons,
435436
returnng next, 455456
returnng pror, 456457
type szng, 463
XML, 605608
LLSL, 342343
LLSll, 342343
employees tube, l8l9
enubng construnts, 3093l0
enubng trggers, 374
encrypton, LC, 525528
LND ll, 342343
endng trunsuctons, 263
envronment vurubes, 533535
equu (=). = (equu)
equons
delned, 46
SLLLC1 stutements usng
mutpe tubes, 4950
SQL/92 syntux, 5758
eru lormuttng purumeters, l35
LRASL( )
dutu lrom CLC, 5l0
delned, 483
LC methods, 488489
errors
exceptons. exceptons
snge-row subqueres, l72l73
vewng n procedures, 362
exceptons
DLl_VAL_CN_lNDLX, 356
lNVALlD_NLMLR, 356357
C1HLRS, 357
lL/SQL, 353355
runnng SQL usng }uvu,
553554
thrown by methods.
methods
ZLRC_DlVlDL, 355356
executon puns, 562, 59l598
LXlS1S( ), 449, 452453
LXlS1S
vs. lN, 586587
correuted subqueres, l76l79
vs. DlS1lNC1, 587
LXl1, 25, 86
LXl( ), 99
LXlLAlN lLAN, 594
expressons
urthmetc, 3l34
CASL. CASL expressons
reguur expresson lunctons,
l09ll6
usng wth lunctons, 98
XMLlARSL( ), 6l3
LX1LND( ), 449, 453
Lxtensbe Murkup Lunguuge (XML).
XML (Lxtensbe Murkup
Lunguuge)
LX1RAC1( ), l55l57

lL1CH, 347
llLLCLCSL( ), 483, 489
llLLCLCSLALL( ), 483, 489
llLLLXlS1S( ), 483, 490
llLLCL1NAML( ), 483, 490
llLLlSClLN( ), 483, 49049l
llLLClLN( ), 483, 49l
les
llLLs. llLLs (bnury
llLL types)
copyng dutu lrom CLCs und
LCs nto, 5l55l7
copyng dutu lrom nto CLCs
und LCs, 5l25l5
suvng/retrevng/runnng, 6670
lterng rows
wth HAVlNC, l25l26
wth \HLRL, 58058l
\HLRL vs. HAVlNC,
584585
lndng trggers, 37l372
llRS1, 2l6, 233
llRS1( ), 449, 454
first_name, l4
llRS1_VALLL( ), 229230
lushbuck dutu urchves, 334337
lushbucks, query, 270273
lLCCR( ), 99, l00l0l
looters, 8283
lCR oops
ce uccess usng, 24024l
cursors und, 349350
delned, 343, 344345
loregn keys
uddng, 308309
construnts enlorcement,
257258
delned, 306
lorests
XMLACC( ), 6096l2
XMLlCRLS1( ), 608609
lCRMA1 format, 707l
lormuts, dutetme
converson, l3ll39
dute, l30
deluut, l39l40
two-dgt yeur nterpretuton,
l40l42
lormuttng herurchcu query resuts,
l99200
lorwurd sush (). (lorwurd
sush)
lrugments, XML, 6l2
lRLL1LMlCRARY( ), 484, 492
lRCM, l7ll72
lRCM_1Z( ), l55, l57
lu outer ons, 60
luy quuled coumn relerences, 582
luncton-bused ndexes, 322323
lunctons, 89l27
uggregute, ll7l20
unuytc. unuytc lunctons
ANSl nested tube support,
469472
cung n puckuges, 367368
wth CAS1( ), 443444
churucter, 9098
lndex

converson, l02l09
CLRRLN1V( ), 239240
dutetme, l42l46
dutetme converson,
l3ll39
DLCCDL( ), l9ll93
DLRLl( ), 39l392
get_product(), 398399
get_product_ref(), 400
get_products(), 395396
CRCLl_lD( ), 2l52l6
CRCLllNC( ), 2092ll
groupng rows, l20l27
CRCLllNC_lD( ), 2l22l4
lS Cl( ), 4084l2
numerc, 98l02
lL/SQL, 363365
RLl( ), 390392
reguur expresson, l09ll6
snge-row, 90
storng returned vuues wth
bnd vurubes, 590
summury, l27
SYS_1YlLlD( ), 4l6
1ALL( ), 436438
tmestump, l54l59
1RANSLA1L( ), l90l9l
1RLA1( ), 4l24l6
usng obects n lL/SQL,
394395
XMLACC( ), 6096l2
XMLA11RlL1LS( ), 608
XMLCCLA11VAL( ), 6l2
XMLCCMMLN1( ), 6l4
XMLCCNCA1( ), 6l3
XMLLLLMLN1( ), 605608
XMLlCRLS1( ), 608609
XMLlARSL( ), 6l3
XMLll( ), 6l4
XMLQLLRY( ), 6l8622
XMLSLQLLNCL( ), 6l5
XMLSLRlALlZL( ), 6l6

generuzed nvocuton, 423425


CL1 filename, 67
get methods, 540542, 545546
CL1CHLNKSlZL( ), 484, 492
getConnection(), 537538
CL1LLNC1H( ), 484, 493
get_product(), 394, 398399
get_product_ref(), 395, 400
get_products(), 394,
395396
CL1_S1CRACL_LlMl1( ),
484, 492
CM1 (Creenwch Meun 1me),
l46l47
CRAN1, 4
gruntng prveges
obect, 282
roes, 290
to users, 278279
usng wth roes, 293
gruntng roes, 29029l
greuter thun (>). > (greuter thun)
greuter thun or equu (>=). >=
(greuter thun or equu)
Creenwch Meun 1me (CM1),
l46l47
CRCLl Y, l20l27
CRCLl Y, extended cuuses
CLL, 207208
delned, 203204
CRCLl Y coumn use, 2l4
CRCLl_lD( ), 2l52l6
CRCLllNC( ), 2092ll
CRCLllNC SL1S, 2ll2l2
CRCLllNC_lD( ), 2l22l4
mutpe coumn use, 2l4
RCLLLl, 205207
CRCLl_lD( ), 2l52l6
CRCLllNC( ), 2092ll
groupng lunctons
groupng rows, l20l27
types ol, ll7l20
CRCLllNC SL1S
vs. CLL, 588
delned, 2ll2l2
usng wth unuytc lunctons,
22l223
CRCLllNC_lD( ), 2l22l4

hundng dutubuse nu vuues,


550552
hundng exceptons. exceptons
hundng nu und mssng vuues,
24l243
hundng numbers, 549550
HAVlNC
groupng rows, l25l27
subqueres n, l70l7l
vs. \HLRL, 584585
heuders, 8283
HLADlNC heading, 707l
hep, SQL*lus, 8586
herurchcu queres
delned, l96l99
emnutng nodes und brunches,
20l202
lormuttng resuts, l99200
ncudng other condtons,
202203
S1AR1 \l1H subquery,
20020l
sturtng ut node other thun
root, 200
truversng upwurd through
tree, 20l
herurches ol obect types,
403405
hnts, pussng to optmzer,
598600
hour lormuttng purumeters, l34
hypothetcu lunctons, 2l6, 235

lD
CRCLl_lD( ), 2l52l6
CRCLllNC_lD( ), 2l22l4
SYS_1YlLlD( ), 4l6
dentcu SQL stutements, 588589
dentlers, row, 30
ll, 342343
lCNCRL NAV, 243
mpct converson, 523524
mportng }DC puckuges, 536537
lN
ANSl nested tube support,
465466
compurng obect vuues,
392394
delned, 39
vs. LXlS1S, 586587
vs. LXlS1S n correuted
subqueres, l78
mutpe-row subqueres,
l73l74
outer on mtutons, 54

Cruce Dutubuse llg SQL


procedure purumeters, 358
usng, 4l42
lN CL1, 358
ncusve runge, 42
ndexes
uddng to tubes, 584
DLl_VAL_CN_lNDLX
exceptons, 356
overvew, 320325
summury, 337
INF (nlnty), 24
nlormuton retrevu
lrom CLCs, 479480
coectons, 43l433
coumn comments,
3l33l4
construnts, 3l03l2
ndexes, 323324
puckuges, 368
lL/SQL lunctons, 365
procedures, 36l362
sequences, 3l63l7
tube comments, 3l3
tubes. Scc dutubuse tube
nlormuton retrevu
trggers, 372374
usng DLSCRlL to get obect
type nlormuton, 382383
vews, 330332
XML schemu, 625630
nhertunce, type, 403405
lNl1CAl( ), 9l93
nne vews, l7ll72
nner ons, 50, 5660
lNSLR1
uddng rows, 202l,
252254
delned, 3
usng }DC, 547548
usng vew, 328329
insert_product(), 394, 397
lNS1R( ), 9l, 93, 484
LC methods, 493494
seurchng dutu n CLC,
5l05ll
nstructons, processng, 6l4
lN1LCLR, l3
ntegrty, dutubuse, 256258
nterluces, 573
nterrow cucuutons wth MCDLL.
Scc MCDLL
lN1LRSLC1, l84, l88l89
lN1LRVAL DAY 1C SLCCND,
l62l64
lN1LRVAL YLAR 1C MCN1H,
l59l62
ntervus, tme, l59l65
lNVALlD_CLRSCR, 354
lNVALlD_NLMLR, 354,
356357
nverse percente lunctons, 2l6,
224225
nvocuton, generuzed, 423425
lS A SL1, 47047l
lS ANY, 238239
lS LMl1Y, 47l
lS lNllNl1L, 39
lS NAN, 39
lS NLLL, 39
lS Cl( ), 4084l2
lS lRLSLN1, 24l242
souted trunsuctons, 265
souton eves, trunsucton,
267269
lSClLN( ), 484, 494495
lS1LMlCRARY( ), 484, 495496

}uvu
runnng SQL usng. Scc SQL
(Structured Query Lunguuge),
runnng usng }uvu
SQL Deveoper computbty, 8
types, 544545
}AVA_HCML envronment
vurube, 534
}DC. Scc ao SQL (Structured
Query Lunguuge), runnng usng
}uvu
cosng obects, 554556
mportng puckuges, 536537
Cruce drvers, 535536
Cruce extensons, 567568
regsterng drvers, 537
Statement obect, 542543
ons
condtons und types, 50
lN (con|nucd) executon puns nvovng tube,
596597
MLRCL, 26l
non-equons, 505l
outer ons, 5l55
quuled coumn
relerences, 582
SLLLC1 stutements usng
mutpe tubes, 4950
SLLLC1 stutements usng two
tubes, 4547
sel ons, 5556
tube ons vs. mutpe queres,
58l582
usng SQL/92 syntux, 566l
}LS1llY, 707l

KLLl NAV, 243


keys
ussocutve urruys, 462
prmury und loregn, 257258

LAC( ), 2l6, 232233


urge obects (LCs). Scc LCs (urge
obects)
LAS1, 2l6, 233
LAS1( ), 449, 454455
LAS1_DAY( ), l43l44
last_name, l5
LAS1_VALLL( ), 229230
LD_LlRARY_lA1H envronment
vurube, 535
LLAD( ), 2l6, 232233
eul nodes, l97
elt outer ons, 5253, 59
ength, l3
LLNC1H( ), 9l, 94
ess thun (<). Scc < (ess thun)
ess thun or equu (<=). Scc <= (ess
thun or equu)
LLVLL pseudo coumn, l98l99
LlKL
compurng obect vuues, 393
delned, 39, 404l
lndex

LlMl1( ), 449
ne sze settng, 73
neur regresson lunctons, 2l6,
233235
Lnux, CRACLL_HCML
envronment vurube, 533534
LlS1, 6566
stng bnd vurubes, 590
LN( ), 99
LCADLClRCMllLL( ),
484, 497
LCADCLClRCMllLL( ), 484,
497498
LCADlRCMllLL( ), 484, 496
LCMAXSlZL, 484
LCs (urge obects)
AllLND( ), 485
uppendng dutu to CLC,
506507
CLCSL( ), 485
CCMlARL( ), 486487
compurng dutu n CLCs,
507508
CClY( ), 487
copyng dutu lrom llLL nto
CLCs und LCs, 5l7520
copyng dutu lrom CLCs,
508509
copyng dutu lrom CLCs und
LCs nto les, 5l55l7
copyng dutu lrom le nto
CLCs und LCs, 5l25l5
CRLA1L1LMlCRARY( ), 488
LRASL( ), 488489
erusng CLC dutu, 5l0
exumpe les, 476477
llLLCLCSL( ) und
llLLCLCSLALL( ), 489
llLLLXlS1S( ), 490
llLLCL1NAML( ), 490
llLLlSClLN( ), 49049l
llLLClLN( ), 49l
lRLL1LMlCRARY( ), 492
CL1CHLNKSlZL( ), 492
CL1LLNC1H( ), 493
CL1_S1CRACL_LlMl1( ), 492
lNS1R( ), 493494
ntroducton, 476
lSClLN( ), 494495
lS1LMlCRARY( ), 495496
LCADLClRCMllLL( ), 497
LCADCLClRCMllLL( ),
497498
LCADlRCMllLL( ), 496
LCNC und LCNC RA\ types,
52l522
ClLN( ), 498499
Cruce dutubuse l0g
enhuncements, 523525
Cruce dutubuse llg
enhuncements, 525529
n lL/SQL, 482484
RLAD( ), 499500
reudng dutu lrom CLCs und
LCs, 504506
retrevng ocutor,
503504
seurchng CLC dutu,
5l05ll
n SQL, 478482
SLS1R( ), 50050l
summury, 529530
tubes contunng, 478
temporury CLCs, 5095l0
1RlM( ), 50l502
types, 477478
\Rl1L( ), 502
\Rl1LAllLND( ), 503
wrtng to CLC, 506
XMLSLRlALlZL( ), 6l6
ocu tme zones, l53l54, l59
LCCAL1lMLS1AMl, l55l56
ocutors, LC, 478, 503504
ocks, trunsucton, 266267
LCC( ), 99
ogc, condtonu, 342343
ogcu operutors, 43
ogcu unt ol work, 262
LCClN_DLNlLD, 354
LCNC RA\ types, 52l522
LCNC types, 52l522
ookng up, 539
oops
ce uccess usng lCR,
24024l
cursors und, 349350
lL/SQL, 343345
LC\LR( ), 9l, 9495
ower bounds, lCR oops,
344345
LlAD( ), 9l, 95
L1RlM( ), 9l, 95

\acbc|h (Shukespeure), 477


mup method, 440442
MAX( ), ll7, ll9
MLMLR Cl, 469470
MLRCL, 259262
metuchuructers
ler-nluenced, ll2
reguur expressons, l09ll2
method overoudng, 420
method overrdng, 422423
methods
AllLND( ), 485
CLCSL( ), 485
CCMlARL( ), 486487
CClY( ), 487
CCLN1( ), 44845l
CRLA1L1LMlCRARY( ), 488
DLLL1L( ), 45l452
LRASL( ), 488489
LXlS1S( ), 452453
LX1LND( ), 453
llLLCLCSL( ) und
llLLCLCSLALL( ), 489
llLLLXlS1S( ), 490
llLLCL1NAML( ), 490
llLLlSClLN( ), 49049l
llLLClLN( ), 49l
llRS1( ), 454
lRLL1LMlCRARY( ), 492
generuzed nvocuton,
423425
CL1CHLNKSlZL( ), 492
getConnection(), 537538
CL1LLNC1H( ), 493
CL1_S1CRACL_LlMl1( ), 492
lNS1R( ), 493494
lSClLN( ), 494495
lS1LMlCRARY( ), 495496
LAS1( ), 454455
LCADLClRCMllLL( ), 497
LCADCLClRCMllLL( ),
497498
LCADlRCMllLL( ), 496
NLX1( ), 455456
ClLN( ), 498499
lRlCR( ), 456457
RLAD( ), 499500
SLS1R( ), 50050l
1RlM( ), 457458, 50l502

Cruce Dutubuse llg SQL


\Rl1L( ), 502
\Rl1LAllLND( ), 503
MlN( ), ll7, ll9
mnus (), 3l
MlNLS, l84, l88
mnute lormuttng purumeters, l34
mssng vuues, hundng, 24l243
mxed notuton, 36l
MCD( ), 99, l0l
MCDLL
u ces uccess usng ANY und
lS ANY, 238239
ce uccess usng lCR oop,
24024l
ce runge uccess usng
L1\LLN und AND, 238
current dmenson vuues usng
CLRRLN1V( ), 239240
delned, 236237
nu und mssng vuues
hundng, 24l243
postonu und symboc
notuton, 237238
updutng exstng ces, 243244
modes, 358
modlyng eements, 438440
MCN, l30
months
dutetme lunctons, l42l44
deluut lormut, l30
lormuttng purumeters, l33l34
lN1LRVAL YLAR 1C MCN1H,
l59l62
MCN1HS_L1\LLN( ), l43l44
movng uveruge, 227228
muteve coectons, 45846l
mutpe uggregute lunctons,
247248
mutpe-coumn subqueres, l68, l75
mutpe queres
vs. CASL expressons, 583
vs. tube ons, 58l582
mutpe-row subqueres, l68,
l73l75
mutpe set operutors, l88l89
MLL1lSL1, 467469

name, l5, l7
numed notuton, 36l
numes, tme zone, l49
NAN (not u number), 24
nutve muchne code generuton, 377
NCLCs (Nutonu Churucter
Set LCs)
compresson, 529
delned, 477478
encrypton, 526528
mpct converson, 523524
LCADCLClRCMllLL( ),
497498
nested subqueres, l68, l79l80
nested tubes
ANSl support, 464472
compurng contents wth mup
method, 440442
convertng wth CAS1( ),
443444
delned, 428
nlormuton retrevu, 432433
munpuutng, 446448
modlyng eements, 439440
muteve coectons, 45846l
popuutng wth eements,
434435
retrevng eements lrom, 436
storuge tube tubespuce,
463464
types, 429430
usng 1ALL( ) wth, 438
NLX1( ), 449, 455456
NLX1_DAY( ), l43l45
nextval, 3l73l9, 376
NLS_DA1L_lCRMA1, l39l40
NCCACHL, 3l9
NC_DA1A_lCLND, 354
nodes
delned, l97
emnutng, 20l202
other thun root, 200
non-equons, 505l
non-dentcu SQL stutements, 588
nonrepeutube reuds, 268
normuzed tme zones, l53l54
NC1
delned, 40, 43
vs. NC1 LXlS1S n correuted
subqueres, l78
not u number (NAN), 24
not equu (!=), 3839
not equu (<>). Scc <> (not equu)
NC1 LXlS1S, l76l79
NC1 lN, 465466
NC1 lNS1AN1lALL types,
4l64l8
NC1 NLLL, 306, 307308
notuton
cung procedures, 36036l
postonu und symboc,
237238
NC1_LCCCLD_CN, 354
N1lLL( ), 2l8, 223224
nu vuues
controng runkng, 2l9
dutubuse tube nlormuton
retrevu, 3537
hundng, 24l243,
550552
NC1 lN und, 42
speclyng lor coumns, 253
NLLLS llRS1, 2l9
NLLLS LAS1, 2l9
NLMLR( ), l3
NLMLR, 23
numbers
hundng, 549550
rows, 303l
numerc coumns, 305
numerc lunctons, 90, 98l02
NLM1CDSlN1LRVAL( ), l64l65
NLM1CYMlN1LRVAL( ), l65
NVL( ), 36, 9l, 96
NVL2( ), 9l, 96

obect dentlers (ClDs), 390392


obect prveges
delned, 28l287
gruntng to roes, 292293
revokng, 288
synonyms, 287288
obects, dutubuse. Scc dutubuse
obects
CCl (Cruce Cu lnterluce)
drvers, 536
ollsets, tme zone, l49
ClDs (obect dentlers),
390392
CN, 5657
CNLY, 4l04ll
ClLN( ), 484, 498499
ClLN-lCR, 35035l
openng cursors, 346
operunds, 3l
methods (con|nucd)
lndex

operutors
ANSl nested tube support,
46447l
urthmetc, 3l34
combnng set operutors,
l88l90
compurng obect vuues,
392394
correuted subqueres, l76
ons. ons
ogcu, 43
mutpe-row subqueres, l73
precedence, 44
set operutors, l84l88
snge-row subqueres, l69l70
SQL, 3943
vuue compurson, 3739
optmzers
hnts, 598600
query costs compurson,
59l598
CR, 43, 55, 6566
Cruce
connectng to dutubuse wth
dutu source, 539542
}DC. }DC
two-dgt yeur nterpretuton,
l40l42
types, 544545, 635638
XML und. XML (Lxtensbe
Murkup Lunguuge)
Cruce Cu lnterluce (CCl)
drvers, 536
Cruce dutubuse l0
ANSl nested tube support,
464472
ussocutve urruys, 462
coectons enhuncements,
46l462
cost-bused optmzuton, 59l
eement type szng, 463
ncreusng eements n
vurruy, 463
LC enhuncements, 523525
nested tube's storuge tube
tubespuce, 463464
vurruys n temporury tubes, 463
Cruce dutubuse ll
generuzed nvocuton leuture,
423425
LC enhuncements, 525529
new lL/SQL leutures, 374377
Cruce Lnterprse Munuger
Dugnostcs luck, 600
Cruce ntroducton, l26
lNARY_lLCA1 und lNARY_
DCLLL types, 2325
DDL stutements used to creute
store schemu, ll20
lL/SQL, 2526
quttng SQL*lus, 25
reutonu dutubuses, 23
rows, uddng/modlyng/
removng, 2023
SQL, 34
SQL Deveoper, 7l0
SQL*lus, 47
store schemu, l0ll
summury, 26
CRACLL_HCML envronment
vurube, 533534
oracle.jdbc puckuge, 57l575
oracle.sql puckuge, 56857l
CRDLR Y, 4445, l72l73
C1HLRS exceptons, 357
CL1, 358
outer ons
delned, 50, 5l55
SQL/92 syntux, 5960
output, combnng coumn, 35
output nes, 7576
overoudng methods, 420
overrdng methods, 422423

puckuges
delned, 365368
mportng }DC, 536537
puge sze, settng, 7273
purumeters
convertng dutetme usng 1C_
CHAR( ), l33l35
procedures, 358359
1C_CHAR( ), l05l06
user-delned constructors,
4l8422
purent nodes, l97
purent tubes, 257258
purentheses ( ), 34, l68
pursng
delned, 562
XMLlARSL( ), 6l3
lAR1l1lCN Y, 22022l
pusswords, lll2, 277278
lA1H envronment vurube, 534
percent (%), 404l
lLRCLN1_RANK( ), 2l8, 223
perlormunce speed, 23
ler-nluenced metuchuructers, ll2
phuntom reuds, 267268
phone, l5
llVC1
delned, 244
exumpe, 244246
mutpe uggregute lunctons n,
247248
on mutpe coumns, 246247
lL/SQL (lroceduru Lunguuge/SQL),
339377
bock structure, 340342
n coectons, 444448
condtonu ogc, 342343
CCLN1( ), 44845l
cursor steps, 346348
cursors, 345346
cursors und lCR oops,
349350
dutubuse obects n, 394395
DLLL1L( ), 45l452
delete_product(), 40040l
display_product(),
396397
DLl_VAL_CN_lNDLX
exceptons, 356
exceptons, 353355
LXlS1S( ), 452453
LX1LND( ), 453
llRS1( ), 454
lunctons, 363365
get_product(), 398399
get_product_ref(), 400
get_products(), 395396
insert_product(), 397
ntroducton, 2526
lNVALlD_NLMLR exceptons,
356357
LAS1( ), 454455
LCs n, 482484.
LCs (urge obects)
oops, 343345
new Cruce Dutubuse ll
leutures, 374377
NLX1( ), 455456
ClLN-lCR stutement, 35035l
Cruce dutu types, 638

Cruce Dutubuse llg SQL


C1HLRS exceptons, 357
puckuges, 365368
lRlCR( ), 456457
procedures, 358362
product_cursor.sq exumpe,
348349
product_lifecycle(),
40l402
product_lifecycle2(),
402403
storng returned vuues
lrom luncton wth bnd
vurube, 590
subtype n puce ol supertype,
406407
summury, 377
1RLA1( ) n, 4l44l6
trggers, 369374
1RlM( ), 457458
unconstruned cursors,
352353
update_product(), 399
update_product_
price(), 398
user-delned constructors,
4l8422
vurubes und types, 342
wrtng XML dutu to le,
6l66l8
ZLRC_DlVlDL exceptons,
355356
pun tubes, 592593
puns, executon, 562, 59l598
pus (+). Scc + (pus)
ponters, 482
popuutng coectons, 434435
popuutng LCs
llLLs, 482
CLCs und LCs, 479
popuutng prmury keys, 3l9
popuutng ResultSet obect,
543544
postonu notuton
udvunced queres, 237238
cung procedures, 36036l
pound (r), l07
lC\LR( ), 99, l0l
lC\LRMLL1lSL1( ), 472
lC\LRMLL1lSL1_Y_
CARDlNALl1Y( ), 472
precson, l3
predelned exceptons, 354355
prepured SQL stutements, 562564
lRLSLN1NNV( ), 242243
lRLSLN1V( ), 242
price, l7
prmury keys
construnts enlorcement, 257
delned, 306
popuutng wth sequences, 3l9
prntng bnd vurubes, 590
lRlCR( ), 449, 456457
prvute tems, 365
prveges
uudtng, 295
checkng roe, 29l292
gruntng obect to roes,
292293
obect, 28l287
query lushbucks, 270
revokng obect, 288
summury, 297298
synonyms, 287288
user, 27828l
vews, 327
lroceduru Lunguuge/SQL (lL/SQL).
Scc lL/SQL (lroceduru
Lunguuge/SQL)
procedures
uppendng dutu to CLC,
506507
cung n puckuges, 367368
compurng dutu n CLCs,
507508
copyng dutu lrom CLCs,
508509
copyng LC dutu. Scc copyng
LC dutu
delned, 358362
delete_product(), 40040l
display_product(),
396397
erusng CLC dutu, 5l0
insert_product(), 397
product_lifecycle(),
40l402
product_lifecycle2(),
402403
reudng dutu lrom CLCs und
LCs, 504506
retrevng LC ocutors, 503504
seurchng CLC dutu, 5l05ll
temporury CLCs, 5095l0
trggers, 369374
update_product(), 399
update_product_
price(), 398
usng obects n lL/SQL,
394395
wrtng to CLC, 506
processng dutetme. Scc dutetme
processng nstructons, 6l4
product_cursor.sq exumpe,
348349
product_id, l6, l7l8
product_lifecycle(),
40l402
product_lifecycle2(),
402403
products tube, l5l6
product_type_id, l5l7
product_types tube, l5l6
lRCCRAM_LRRCR, 354
progrummng unguuges
lL/SQL. Scc lL/SQL (lroceduru
Lunguuge/SQL)
SQL*lus. Scc SQL*lus
XML. Scc XML (Lxtensbe
Murkup Lunguuge)
pseudo coumns
delned, 30
LLVLL, l98l99
sequences, 3l73l9
pubc synonyms, 287288
purchases tube, l7l8

quantity, l8
quurter lormuttng purumeters, l33
queres
costs compurson, 59l598
delned, 28
lushbucks, 270273
subqueres. Scc subqueres
tunng SQL. Scc SQL (Structured
Query Lunguuge) tunng
usng }DC, 543547
XMLQLLRY( ), 6l8622
queres, udvunced, l83250
u ces uccess usng ANY und
lS ANY, 238239
lL/SQL (con|nucd)
lndex

unuytc lunctons, 2l62l7


CASL expressons, l93l96
ce uccess usng lCR oop,
24024l
ce runge uccess usng
L1\LLN und AND, 238
CLL, 207208
current dmenson vuues usng
CLRRLN1V( ), 239240
DLCCDL( ), l9ll93
emnutng nodes und brunches,
20l202
llRS1 und LAS1 lunctons, 233
lormuttng herurchcu resuts,
l99200
CRCLl Y, 203204
CRCLl Y coumn use, 2l4
CRCLl_lD( ), 2l52l6
CRCLllNC( ), 2092ll
CRCLllNC SL1S, 2ll2l2
CRCLllNC_lD( ), 2l22l4
herurchcu, l96l99
herurchcu, ncudng other
condtons, 202203
hypothetcu runk und
dstrbuton lunctons, 235
nverse percente lunctons,
224225
LAC( ) und LLAD( ), 232233
neur regresson lunctons,
233235
MCDLL, 236237
mutpe uggregute lunctons n
pvot, 247248
nu und mssng vuues
hundng, 24l243
llVC1 und LNllVC1, 244
llVC1 exumpe, 244246
pvotng on mutpe coumns,
246247
postonu und symboc
notuton, 237238
runkng lunctons, 2l7224
reportng lunctons, 230232
RCLLLl, 205207
set operutors, l84l88
set operutors, combnng,
l88l90
S1AR1 \l1H subquery, 20020l
sturtng ut node other thun
root, 200
summury, 249250
1RANSLA1L( ), l90l9l
truversng upwurd through
tree, 20l
LNllVC1, 248249
updutng exstng ces,
243244
wndow lunctons, 225230
query stutements, SQL, 3
queston murk (:), 564
quttng SQL *lus, 25
quotes ("), 34, 254

runge, 23
runk, hypothetcu lunctons, 235
runkng lunctons, 2l6, 2l7224
RA1lC_1C_RLlCR1( ), 23l232
RA\ types, 52l
RLAD( ), 484, 499500,
504506
RLAD CCMMl11LD, 268
RLAD CNLY, 306, 330
RLAD LNCCMMl11LD, 268
RLl( ), 390392
RLl CLRSCR, 35l, 59059l
relerences, obect, 383,
390392
RLCLXl_CCLN1( ), ll4, ll6
RLCLXl_lNS1R( ), ll3, ll5
RLCLXl_LlKL( ), ll3, ll4ll5
RLCLXl_RLlLACL( ), ll4, ll6
RLCLXl_SLS1R( ), ll4, ll6
reguur expresson lunctons, 90,
l09ll6
reguur expressons
lunctons, ll3ll6
metuchuructers, l09ll2
reutonu dutu, generutng XML. Scc
XML (Lxtensbe Murkup
Lunguuge)
reutonu dutubuses, 23
removng rows, 256
RLNAML, 3
renumng tubes, 3l3
RLlLA1ALL RLAD, 268
RLlLACL( ), 9l, 9697
reportng lunctons, 2l6,
230232
reports, 7985
resut set
delned, 28
retrevng rows usng }DC,
543547
resuts, herurchcu query, l99200
retrevng nlormuton. Scc
nlormuton retrevu
RL1LRNlNC, 255256
RLVCKL, 4
revokng prveges
obect, 288
lrom users, 28l
revokng roes, 294
rght outer ons, 5254, 5960
roes
checkng prveges,
29l292
creutng, 289
deluut, 294
droppng, 295
grunted prvege use, 293
grunted to users, 29029l
gruntng obect prveges,
292293
gruntng prveges, 290
revokng, 294
summury, 297298
RCLLACK
delned, 4
row removu, 2223
trunsuctons, 262263
RCLLLl
delned, 205207
CRCLllNC( ), 2092l0
usng wth unuytc lunctons,
22l223
Romco and }uc|
(Shukespeure), ll0
root nodes
delned, l97
sturtng ut node other thun, 200
rotutng. Scc llVC1
RCLND( )
dutetme lunctons,
l43, l45
delned, 99, l0l
row-eve trggers, 369
RC\lD, 30
RC\NLM, 303l
RC\_NLMLR( ), 2l8, 224

Cruce Dutubuse ll SQL


rows
uddng/modlyng/removng,
2023
uddng usng }DC, 547548
chungng tube contents.
tube contents, chungng
delned, 2
deetng usng }DC, 548
dspuyng dstnct, 37
lterng wth \HLRL, 58058l
gettng lrst und ust, 229230
groupng, l20l27
dentlers, 30
modlyng usng }DC, 548
mutpe-row subqueres,
l73l75
numbers, 303l
pvotng. llVC1
removng dupcute wth
CRCLl_lD( ), 2l52l6
retrevng speclc usng
\HLRL, 29
retrevng usng }DC, 543547
retrevng wth cursors.
cursors
snge-row subqueres, l68l73
sortng, 4445
storng wth bnd vurube,
59059l
usng 1ALL( ) to treut coecton
us seres ol, 436438
RC\1YlL_MlSMA1CH, 354
RlAD( ), 9l, 95
RR lormut, l40l42
R1RlM( ), 9l, 95
rue-bused optmzuton, 59l
RLLLS LlDA1L, 243244
RLN, 65
run-tme checks, 4l24l6
run-tme errors hundng.
exceptons

salary_grades tube, l920


SAVLlClN1, 4
suveponts, 264265
suvng SQL*lus les, 6670
suvng XML
n dutubuse, 622
exumpe le, 623
exumpe schemu, 623625
exumpe schemu nlormuton
retrevu, 625630
exumpe schemu nlormuton
updutng, 630633
scuur subqueres, l70
scue, l3
schemus, 2
schemus, store
DDL stutements, ll20
ntroducton, l0ll
schemus, XML
creutng, 623625
nlormuton retrevu, 625630
nlormuton updutng, 630633
SCNs (system chunge numbers),
272273
scrpts, 7985
seurched CASL expressons,
l94l96
seurchng CLC dutu, 5l05ll
seconds
lormuttng purumeters, l34
lN1LRVAL DAY 1C SLCCND,
l62l64
SLLLC1
uddng rows, 2l
perlormng usng SQL*lus, 67
snge tube nlormuton
retrevu, 2829
usng mutpe tubes, 4950
usng two tubes, 4547
SLLl, 4l9
sel ons, 50, 5556, 60
SLLl_lS_NLLL, 355
semcoon (,), 6, 34l
sepurutors, l34
sequences, 3l4320
creutng, 3l43l6
droppng, 320
modlyng, 320
new Cruce Dutubuse ll
leutures, 375377
popuutng prmury keys, 3l9
retrevng nlormuton, 3l63l7
summury, 337
usng, 3l73l9
XMLSLQLLNCL( ), 6l5
SLRlALlZALL trunsuctons,
268269
server-sde nternu drver, 536
server-sde 1hn drver, 536
sessons
delned, l39
tme zones, l47l49
SL1( ), 470
SL1 LlNLSlZL, 73
set methods, 540542
set operutors, l84l90
SL1 lACLSlZL, 7273
SL1S, CRCLllNC, 2ll2l2
Shukespeure, \um, ll0, 477
SlCN( ), 99, l02
smpe CASL expressons,
l93l94
smpe oops, 343344
smpe vews, 327
SlMlLL_lN1LCLR type, 375
SlN( ), 99
snge-row lunctons
churucter, 9098
converson, l02l09
numerc, 98l02
reguur expresson, l09ll6
types ol, 90
snge-row subqueres, l68l73
SlNH( ), 99
szng coumns, 305
szng eement types, 463
SCML, 3839
sortng rows, 4445
SCLNDLX( ), 9l, 97
specu vuues, 2425
speclcutons, puckuge,
365366, 395
SlCCL, 67
SQL/92
CASL expressons, l93
delned, 47
ons usng, 566l
SQL Access Advsor, 60l
SQL Deveoper, 7l0
SQL (Structured Query Lunguuge)
ntroducton, 34
LCs n, 478482
operutor precedence, 44
operutors, 3943
Cruce dutu types, 636637
lroceduru Lunguuge.
lL/SQL (lroceduru
Lunguuge/SQL)
lndex

subtype n puce ol supertype,


405406
SQL (Structured Query Lunguuge),
runnng usng }uvu, 53l578
uddng rows, 547548
BasicExample1.java,
556562
BasicExample2.java,
565567
BasicExample3.java,
575577
cosng }DC obects, 554556
conlgurng computer, 533535
dutubuse connecton, 537542
dutubuse trunsucton contro,
552553
DDL stutements, 553
deetng rows, 548
gettng sturted, 532
hundng dutubuse nu vuues,
550552
hundng exceptons, 553554
hundng numbers, 549550
mportng }DC puckuges,
536537
}DC Statement obect,
542543
modlyng rows, 548
Cruce }DC drvers, 535536
Cruce }DC extensons,
567568
oracle.jdbc puckuge,
57l575
oracle.sql puckuge,
56857l
prepured stutements, 562564
regsterng Cruce }DC
drvers, 537
retrevng rows, 543547
summury, 578
SQL (Structured Query Lunguuge)
tunng, 57960l
uddng ndexes to tubes, 584
uddtonu toos, 60060l
bnd vurubes, 58859l
CASL expressons vs. mutpe
queres, 583
LXlS1S vs. DlS1lNC1, 587
LXlS1S vs. lN, 586587
lterng rows wth \HLRL,
58058l
CRCLllNC SL1S vs.
CLL, 588
ntroducton, 580
ons wth quuled coumn
relerences, 582
pussng hnts to optmzer,
598600
query costs compurson,
59l598
summury, 60l
tube ons vs. mutpe queres,
58l582
LNlCN ALL vs. LNlCN,
585586
\HLRL vs. HAVlNC,
584585
SQL 1unng Advsor, 60060l
SQL*lus, 6387
uutomutcuy generuted
stutements, 86
lNARY_lLCA1 und lNARY_
DCLLL types, 2325
coumn lormut ceurng, 73
coumn lormuttng, 7072
DDL stutements used to creute
store schemu, ll20
dsconnectng/extng, 86
edtng SQL stutements,
6566
les, suvng/retrevng/runnng,
6670
gettng hep, 8586
nlormuton retrevu.
dutubuse tube nlormuton
retrevu
ntroducton, 47
ne sze, settng, 73
puge sze, settng, 7273
quttng, 25
rows, uddng/modlyng/
removng, 2023
smpe reportng, 7985
store schemu, l0ll
summury, 87
tube structure, 6465
vurubes, 7479
SQR1( ), 99, l02
S1AR1 \l1H, l98, 20020l
sturtng trunsuctons, 263
stutement-eve trgger, 369
Statement obect, 542543
stutstcs n cost-bused
optmzuton, 597
S1DDLV( ), ll7, l20
storuge
dutetme. dutetme
delned, 23
numbers n }uvu,
549550
returned vuues wth bnd
vurube, 590
rows wth bnd vurube,
59059l
tubes, 463464
S1CRACL_LRRCR, 355
store schemus
DDL stutements, ll20
ntroducton, l0ll
stored subprogrums, 363
strngs
convertng dutetme usng
1C_CHAR( ), l32l36
convertng dutetme usng
1C_DA1L( ), l36l39
convertng to 1lMLS1AMl
\l1H LCCAL 1lML
ZCNL, l59
XMLSLRlALlZL( ), 6l6
structure, bock, 340342
Structured Query Lunguuge (SQL).
SQL (Structured Query
Lunguuge)
SLMLL1lSL1, 442, 466467
subqueres, l67l8l
correuted, l75l79
mutpe-coumn, l75
mutpe-row, l73l75
nested, l79l80
snge-row, l68l73
S1AR1 \l1H, 20020l
summury, l8l
types ol, l68
LlDA1L, 255
LlDA1L und DLLL1L stutements
contunng, l80l8l
SLSCRll1_LYCND_
CCLN1, 355
SLSCRll1_CL1SlDL_LlMl1, 355
substtuton vurubes, 7479
SLS1R( ), 9l, 9798, 484,
50050l
subtotu computng, 8385

Cruce Dutubuse ll SQL


subtypes
delned, 404
generuzed nvocuton,
423425
lS Cl( ), 4084l2
overrdng methods, 422423
usng n puce ol supertype,
405408
SLM( ), ll7, l20
sums, cumuutve, 225227
sums, reportng on, 23023l
supertypes
delned, 404
generuzed nvocuton,
423425
NC1 lNS1AN1lALL obect
types, 4l64l8
overrdng methods, 422423
subtype, usng n puce ol,
405408
symboc notuton, 237238
synonyms, prveges, 287288
SYSDA1L, 67, l43, l45
SYS_LX1RAC1_L1C( ), l55,
l57l58
SYS_lNVALlD_RC\lD, 355
system chunge numbers (SCNs),
272273
system prveges. prveges
SYS1lMLS1AMl, l55l56
SYS_1YlLlD( ), 408, 4l6

1ALL( ), 436438
tube uuses
delned, 4748
sel ons, 55
tube contents, chungng, 25l273
uddng rows, 252254
dutubuse ntegrty, 256258
dutubuse trunsuctons,
262269
deluut vuues, 258259
mergng rows, 259262
modlyng rows, 254255
query lushbucks, 270273
removng rows, 256
RL1LRNlNC, 255256
summury, 273
tube ons. ons
delned, 46
executon puns nvovng,
596597
vs. mutpe queres,
58l582
tubes, 3003l4
uddng comments, 3l33l4
uddng ndexes to, 584
uterng, 302306
lNARY_lLCA1 und lNARY_
DCLLL, 2425
coumn obects, 383386
compurng obect vuues,
392394
construnts, 3063l2
contunng LCs, 478
creutng, 300302
delnng coumn wth coecton
type, 430
droppng, 3l4
exumnng, l220
gettng nlormuton on,
302303
nlormuton retrevu.
dutubuse tube nlormuton
retrevu
nested. nested tubes
obect tubes, 386389
ClDs und obect relerences,
390392
pun tube, 592593
renumng, 3l3
SQL*lus structure, 6465
storuge tube tubespuce,
463464
substtutng numes usng
vurubes, 7677
summury, 337
truncutng, 3l4
vurruys n temporury, 463
tubespuces, 276, 463464
1AN( ), 99
1ANH( ), 99
1C (1runsucton Contro)
stutements, 4
temporury LCs
CRLA1L1LMlCRARY( ), 488
lRLL1LMlCRARY( ), 492
usng temporury CLCs,
5095l0
temporury tubes, 463
temporury vurubes, 7477, 80
1HLN, 342343
1hn drver, 535536
tme. dutetme
tme query lushbucks, 270272
tme zones, l35, l46l50,
l52l54
1lMLCL1_CN_RLSCLRCL, 355
tmestumps
lushbuck dutu urchves,
334337
lunctons, l54l59
usng, l50l54
1C_CHAR( )
combnng wth 1C_DA1L( ),
l38l39
convertng dutetme, l3ll36
delned, l04l07
1C_DA1L( ), 32, l3ll32, l36l39
1C_NLMLR( ), l07l08
toos, SQL tunng. SQL
(Structured Query Lunguuge)
tunng
1CC_MANY_RC\S, 355
1C_1lMLS1AMl( ), l55, l58
1C_1lMLS1AMl_1Z( ), l55, l58
tru vews, uudtng, 296
1runsucton Contro (1C)
stutements, 4
trunsucton souton eve,
267269
trunsucton ockng, 266267
trunsuctons, dutubuse, 262269,
552553
1RANSLA1L( ), l90l9l
trunspurent roundng, 23
1RLA1( ), 408, 4l24l6
tree queres. herurchcu
queres
delned, l97
emnutng nodes und brunches,
20l202
truversng upwurd through, 20l
trggers
:new uttrbute, 524525
delned, 369374
1RlM( )
delned, 9l, 95, 449,
457458, 484
LC methods, 50l502
lndex

1RLNC( )
dutetme lunctons,
l43, l46
delned, 99, l02
1RLNCA1L, 3, 3l4
try/cutch stutements, 553554
11l1LL, 8283
tunng, SQL. SQL (Structured
Query Lunguuge) tunng
two-dgt yeur nterpretuton,
l40l42
types
chungng coumn, 305
cusses und computbe Cruce
dutubuse types, 568
hundng numbers wth }uvu,
549550
Cruce, 635638
Cruce und }uvu, 544545
lL/SQL, 342
SlMlLL_lN1LCLR, 375
types, coecton
convertng wth CAS1( ),
443444
delned, 429430
delnng coumns wth, 430
eement type szng, 463
types, LC
llLLs. llLLs (bnury
llLL types)
LCs (bnury LCs).
LCs (bnury LCs)
CLCs. CLCs
(churucter LCs)
creutng, 477478
LCNC und LCNC RA\ types,
52l522
NCLCs. NCLCs
(Nutonu Churucter Set LCs)
types, obect
creutng, 38l382
generuzed nvocuton,
423425
nhertunce, 403405
lS Cl( ), 4084l2
NC1 lNS1AN1lALL,
4l64l8
overrdng methods,
422423
subtype n puce ol supertype,
405408
SYS_1YlLlD( ), 4l6
usng DLSCRlL to get
nlormuton, 382383

unconstruned cursors, 352353


LNDLllNL, 7879
underscore (_), 404l
LNlCN
combnng set operutors,
l88l89
delned, l84
vs. LNlCN ALL, 585586
usng, l87
LNlCN ALL
delned, l84
vs. LNlCN, 585586
usng, l86l87
LNlQLL, 306, 309
Lnx, CRACLL_HCML envronment
vurube, 533534
LNllVC1, 244, 248249
LlDA1L
delned, 3
modlyng rows, 22, 254255
stutements contunng
subqueres, l80l8l
usng }DC, 548
update_product(),
394, 399
update_product_price(),
394, 398
updutng
RLLLS LlDA1L, 243244
XML schemu, 630633
LllLR( ), 9l, 9495
upper bounds, 344345
LRL, dutubuse connecton,
538539
user-delned constructors, 4l8422
user vews
nested tubes, 433
vurruys, 43l432
users
uudtng, 295296
creutng, lll2
grunted roes to, 29029l
gruntng obect prveges, 282
overvew, 276278
prveges, 27828l
summury, 297298
LSlNC, 5758, 26l
L1C (Coordnuted Lnversu 1me),
l46l47

VACHAR( ), l3
VALLL( ), 387
VALLL_LRRCR, 355
vuues
ussocutve urruys, 462
compurson, 3739
convertng wth CRCLllNC,
2092l0
dutubuse obects compurson,
392394
decurng vurubes to store
coumn, 346
gettng current, 239240
gettng lrst und ust rows usng,
229230
hundng nu und mssng,
24l243
nu. nu vuues
reudng coumn lrom
ResultSet obect, 544545
storng returned wth bnd
vurube, 590
usng deluut, 258259
vurubes
bnd, 58859l
cursors, 346
CRACLL_HCML envronment,
533534
lL/SQL, 342
n scrpts, 8082
SQL*lus, 7479
VARlANCL, ll7, l20
vurruys
convertng wth CAS1( ),
443444
delned, 428
ncreusng eements n, 463
nlormuton retrevu, 43l432
munpuutng, 444446
modlyng eements, 438439
muteve coectons, 45846l
popuutng wth eements, 434

Cruce Dutubuse llg SQL


retrevng eements lrom, 435
n temporury tubes, 463
types, 429430
usng 1ALL( ) wth, 437438
vews, 325334
creutng/usng, 326333
delned, 325326
droppng, 334
errors n procedures, 362
modlyng, 333334
nested tube nlormuton
retrevu, 433
summury, 337
tube structure, 6465
vurruy nlormuton retrevu,
43l432
vrtuu coumns, 304305

wuets, 525526
week lormuttng purumeters, l34
\HLN NC1 MA1CHLD, 26l
\HLRL
lterng rows wth, 58058l
groupng rows, l26l27
vs. HAVlNC, 584585
herurchcu queres, 202203
retrevng speclc rows, 29
row modlcuton, 22
subqueres n, l68l69
usng SQL operutors, 3943
\HlLL oops, 343, 344
wndow lunctons, 2l6, 225230
\ndows Xl, CRACLL_HCML
envronment vurube, 533
\CRD_\RAllLD, 707l
\RAllLD, 707l
wrupper cusses, 55l552
\Rl1L( ), 484, 502, 506
\Rl1LAllLND( ), 484, 503

x, 6566
XML (Lxtensbe Murkup Lunguuge),
603633
exumpe le, 623
exumpe schemu, 623625
exumpe schemu nlormuton
retrevu, 625630
exumpe schemu nlormuton
updutng, 630633
generutng lrom reutonu
dutu, 604
ntroducton, 604
lL/SQL exumpe, 6l66l8
suvng n dutubuse, 622
summury, 633
XMLACC( ), 6096l2
XMLA11RlL1LS( ), 608
XMLCCLA11VAL( ), 6l2
XMLCCMMLN1( ), 6l4
XMLCCNCA1( ), 6l3
XMLLLLMLN1( ), 605608
XMLlCRLS1( ), 608609
XMLlARSL( ), 6l3
XMLll( ), 6l4
XMLQLLRY( ), 6l8622
XMLSLQLLNCL( ), 6l5
XMLSLRlALlZL( ), 6l6
XQuery expresson, 6l8622

yeurs
dutetme deluut lormut, l30
dutetme lormuttng
purumeters, l33
lN1LRVAL YLAR 1C MCN1H,
l59l62
two-dgt yeur nterpretuton,
l40l42
YY lormut, l40
YYYY, l30

ZLRC_DlVlDL exceptons, 355356


vurruys (con|nucd)
F8EE 8868I FII N
YOU MUST ANSWER ALL TEN OUESTIONS BELOW.

Yes, pIease send me a FREE subscription to OracIe magazine. NO


To receive a Iree subscripIioh Io Orace Nagazne, you musI Iill ouI Ihe ehIire card, sigh iI, ahd daIe iI
(ihcompleIe cards cahhoI be processed or ackhowledged). You cah also Ia your applicaIioh Io +1.847.763.9638.
Or subscribe at our Web site at otn.oracIe.com/oracIemagazine
h a m e I i I l e
c o m p a h y e - m a i l a d d r e s s
s I r e e I / p . o . b o
c i I y / s I a I e / z i p o r p o s I a l c o d e I e l e p h o h e
c o u h I r y I a
s i g h a I u r e ( r e q u i r e d ) d a I e
x
From Iime Io Iime, Oracle Publishihg allows
our parIhers eclusive access Io our e-mail
addresses Ior special promoIiohs ahd
ahhouhcemehIs. To be ihcluded ih Ihis pro-
gram, please check Ihis circle.
Oracle Publishihg allows sharihg oI our
mailihg lisI wiIh selecIed Ihird parIies. I you
preIer your mailihg address hoI Io be
ihcluded ih Ihis program, please check here.
I aI ahy Iime you would like Io be removed
Irom Ihis mailihg lisI, please cohIacI
CusIomer Service aI +1.847.647.9630 or sehd
ah e-mail Io oracle@halldaIa.com.
RAI | I | 1| A1 \ JJ | 4|
A| I| \ | I \ J | \J J1 | | 1 AI I |
| J| AI | J4! (:|-:| ta- ta|j
1I A-|tsj:- a1 J-|-as- aa|:|a||a
1l Ajj||:||ta -|t|:- |tt|1-|
11 Aa|tmt||t- aa|:|a||a
11 ||-m|:|s, J|| a1 s
1a |tmmaa|:||tas a1 -1|
1 |tas||a:||ta/|a|a--||a
1I |tasam-| -:|t|/|tasam-| :|-1 tt1s
1 |1a:||ta
11 ||aa:|| -|t|:-s/|asa|a:-
I1 tt-|am-a| (:|t||j
II tt-|am-a| (m|||||j
Il -|||:|-
I1 || I-:|at|t aa|:|a||a, J|
I1 |a|-||-1 t||w|- \-a1t|
Ia |||- :|-a:-s (J|t|-:|, ||m:-a||:|sj
I |a|a
II 1-|||/R|t|-s|-/J|s||||a||ta
I s|-ms |a|-||t|, \A1/\AJ
I1 I-|-:tmmaa|:||tas
l1 I|t-| a1 I|asjt||||ta
lI J||||||-s (-|-:|||:, s, sa||||ta, w|-|j
1 J||-| Jas|a-ss a1 -|t|:-s
R| | J | I | | J || J R| 4 J| I
J | |1| J| \J J1 1| A1\ J JJ
| J4| I | J 4! (:|-:| ta- ta|j
| t | j t | | - a - m- a | / | | |
1I |t-:a||t- a-m-a| (|-s|1-a|, ||||,
||J, ||J, Jwa-|, ||a-|, ||a:|j|j
1l ||aa:-/A1m|a|s||||t- a-m-a|
(\/J||-:|t|/ a-|/|ta||t||-|,
a|:|s|a, A1m|a|s||||taj
11 |-s/||-||a a-m-a|
(\/J||-:|t|/a-|j
11 |tmja|-| s|-ms/Jj-|||tas a-m-a|
(||J/\/J||-:|t|/ a-| |, Jj-|||tasj
| / | I | | |
1a s|-ms J-t-|tjm-a|/
|t|mm|a a-m-a|
1 s|-ms J-t-|tjm-a|/ |t|mm|a |||
1I |tasa|||a
1 JJA/s|-ms A1m|a|s|||t|
11 |1a:||ta/I||a|a
I1 I-:|a|:| ajjt|| J||-:|t|/a-|
II J||-| I-:|a|:| a-m-a|/|||
1 J||-|
RAI | \J J1 |J 11| 4I 1| A1\
J |1AI | 4 |AI | J1! (s-|-:| || ||| jj|j
1I J|||| |a|jm-a| J4|K
1l J|||| |a|jm-a| \AK \
11 J4|K
11 |J A|K
1a |J J4|K
1 Jt
1I ||aat
1 :|a|ts|
11 -JJ
I1 \
II 4-|R|-
Il 4-|wt|| |tmja||a
I1 Jj-a\
I1 |J J4|K
Ia -a-a| J\4|K/j|t
I aa t|||s/aaJ
II \11
I Ja|tR|-
I1 R|a1tws
l1 R|a1tws 4I
lI J||-| J4|K
1 J||-|
11 4ta- t| ||- |tt-
J J \ JJ | \A|J AI |, | | | |\ ,
1| |J | 4J, J 1 AJ I J 1| l | I |
J 1| A| J | A4\ J | I | | J || J R| 4 !
(:|-:| || ||| jj|j
1I |1w|-
1l t||w|-
11 Ajj||:||ta J-t-|tjm-a| Itt|s
11 J||s- |t1a:|s
1a |a|-|a-| t| |a||a-| |t1a:|s
11 4ta- t| ||- |tt-
| 4 \ JJ 1 J JJ, J J \ JJ J | J1 |A4 I J
J 1| A| A4\ J| I | | J| | JR| 4
1J JJ | I ! (:|-:| || ||| jj|j
t | | w | -
1I Jas|a-ss |j||:s
1l |AJ/|A|/|A
11 |A|
11 |tmmaa|:||tas
1a J||s- a-m-a|
1 |||- a-m-a|
1I ||aa:-
1 Jt
11 |-|||s 1-sta|:- |aa|a
I1 a|||m-1| Aa||t||a
II 4-|wt|||a
Il J|||:- Aa|tm||ta
I1 J|1-| |a||/|at-a|t| |ta||t|
I1 |t|mm|a
Ia |tj-:| a-m-a|
I :|-a||||: a1 |a|a--||a
II j|-1s|--|s
I s|-ms a-m-a|
I1 Rt||||tw
| 1 w | -
l1 :|a|ts|
lI |a||m-
ll ss|t-| |||-| |t:-ss|a
l1 |a|:tmja|-|
l1 |
la 4-|wt|| |tmja|-|
l mm-|||: a|||j|t:-ss|a
lI Rt||s|||ta
- | | j | - | | s
l J||1-s/1ta|-|s/a|s/|-ws
l1 |J-1J J||t-s
11 J|s| J||t-s/a|ss|-ms
1I t1-ms
1l Ij- J||t-s/a|ss|-ms
11 \|1-t Jt|1s/a|||m-1|
- | t | : - s
11 Ajj||:||ta -|t|:- |tt|1-|
1a |tasa|||a
1 |1a:||ta/I||a|a
1I |a|-aa:-
1 Ja||a- J||s- -|t|:-s
11 ajjt||
11 I-:|at|t-Js-1 I||a|a
1 J||-|
11 4ta- t| ||- |tt-
RAI J 1A|| | 1JJ J |I A1| | 4 J |
AI \J J1 | I |! (:|-:| || ||| jj|j
J | : | - | - Ja s | a - s s a | | -
1I J|:|- ||-||a
1l J|:|- |-s
11 J|:|- J|1-| |a|||||m-a|
11 J|:|- ajj| |||a a-m-a|
1a J|:|- |t:a|-m-a|
1 J|:|- aa|:|a||a
1I J|:|- |a|-aa:- a-m-a|
1 J|:|- -|t|:-
11 J|:|- |ta||:|s
I1 J|:|- |tj-:|s
II J|:|- ||aa:||s
Il J|:|- ama 1-sta|:-s
I1 J|:|- |a|-|:||ta |-a|-|
I1 J|:|- |tmmaa|:||tas/J||||||-s (mt1a|-sj
Ia J|:|- a|||: -:|t|/Ja|t-|s|| (mt1a|-sj
I J|:|- ||aa:|| -|t|:-s (mt1a|-sj
- | t - | / t | | w | -
II J|:|-1
I J|:|-1 |||-
I1 J|:|-
l1 J||-| J|:|- 1||s-
lI J|:|-1 Ajj||:||ta -|t-|
ll J|:|-1 Ajj||:||ta -|t-| R||-|-ss
l1 J|:|- m|| Jas|a-ss a||-
I t t | s
l1 J|:|- J-t-|tj-| a||-
la J|:|- J|s:tt-|-|
l J|:|- JJ-t-|tj-|
lI J|:|- ||||ta Rt|||-a:|
l J|:|-1 A t|||
l1 J|:|- R|-|tas- Ja||1-|
J | : | - - | t | : - s
11 J|:|- Ja|sta|:|a
1I J|:|- |tasa|||a
1l J|:|- |1a:||ta
11 J|:|- ajjt||
1 J||-|
11 4ta- t| ||- |tt-
RAI J I | 1 J AI AJA| 1JJ J |I A1|
| 4 J | AI \J J1 | I |! (:|-:| || ||| jj|j
1I A::-ss 1 |:|tst|| A::-ss
1l Ja 11 |:|tst|| J| -|t-|
11 1|s- I1 -tj|-t||
11 aj| II |t|-ss
1a |J JJl Il A
1 |a|t|m|t I1 |s-
1I |a|-s I1 \A
1 J||-|
11 4ta- t| ||- |tt-
RAI J I | 1 A|| | AI | J4 | 1\| 1
1J JJ | I A1| | 4 J | AI \ JJ 1 | I | !
(:|-:| || ||| jj|j
1I J|A
1l |J
11 |s-
11 aa
1a J||-|
J J1| 4 I | 4| KI I l J 4I , J R
J | J J \ J J A4I | | | AI | \ JJ 1
J 1A4| l AI | J 4 R| | | | 4J J4
| JJ I |1 A1JRA1| , J| I RA1|,
| 1| | 1A| , A4J | 1\| | |
| J1 \ J J1 | J| AI | J4 ! (:|-:| ta| ta-j
1I |-ss ||a I1,111
1l I1,111 |t 11,111
11 a1,111 |t 11,111
11 I11,111 |t 111,111
1a a11,111 |t 111,111
1 I,111,111 a1 tt-|
RAI | \J J1 |J A4\' \ | A1| \
A| | 1| \|4 J| ! (j|-s- :|tts- ta-j
1I a11, 111, 111 a1 |tt-
1l I11, 111, 111 |t a11, 111, 111
11 a1, 111, 111 |t I11, 111, 111
11 a, 111, 111 |t a1, 111, 111
1a I, 111, 111 |t a, 111, 111
1
2
3
4
8
9
10
6
5
7

You might also like