Oracle Database 11g SQL Parte 3
Oracle Database 11g SQL Parte 3
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.
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 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;
/
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
);
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.
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
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
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.
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>
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
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.
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
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
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
}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
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
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
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
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
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
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
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
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