0 évaluation0% ont trouvé ce document utile (0 vote)
23 vues19 pages
%is appendix provides several PL / SQL Programs to guide you in writing your own. Ou can Iind te online Iiles in te demo directory. For te location oI te directory, see te installation or user's guide.
%is appendix provides several PL / SQL Programs to guide you in writing your own. Ou can Iind te online Iiles in te demo directory. For te location oI te directory, see te installation or user's guide.
Droits d'auteur :
Attribution Non-Commercial (BY-NC)
Formats disponibles
Téléchargez comme DOCX, PDF, TXT ou lisez en ligne sur Scribd
%is appendix provides several PL / SQL Programs to guide you in writing your own. Ou can Iind te online Iiles in te demo directory. For te location oI te directory, see te installation or user's guide.
Droits d'auteur :
Attribution Non-Commercial (BY-NC)
Formats disponibles
Téléchargez comme DOCX, PDF, TXT ou lisez en ligne sur Scribd
A SampIe PL/SQL Programs %is appendix provides several PL/SQL programs to guide you in writing your own. %e sample programs illustrate several important PL/SQL concepts and Ieatures. %is appendix discusses te Iollowing topics: Running te Programs Sample 1. FOR Loop Sample 2. Cursors Sample 3. Scoping Sample 4. Batc %ransaction Processing Sample 5. Embedded PL/SQL Sample 6. Calling a Stored Procedure #:333g the Programs ll te sample programs in tis appendix and several oters trougout tis guide are available online. So, tey are preceded by te Iollowing comment: -- available online in file '<filename'
ou can Iind te online Iiles in te PL/SQL demo directory. For te location oI te directory, see te Oracle installation or user's guide Ior your system. Here is a list oI te Iiles and teir locations in tis guide: Ie3ame Locato3 3 Ths G:/e examp1 "Understanding te Main Features oI PL/SQL" examp2 "Conditional Control" examp3 "Iterative Control" examp4 "Using liases" Ie3ame Locato3 3 Ths G:/e examp7 "Using Cursor FOR Loops" examp8 "Passing Parameters to a Cursor FOR Loop" examp5 "Some Examples oI Cursor ttributes" examp6 "Some Examples oI Cursor ttributes" examp11 "Example" examp12 "Examples" examp13 "Examples" examp14 "Examples" sample1 "Sample 1. FOR Loop" sample2 "Sample 2. Cursors" sample3 "Sample 3. Scoping" sample4 "Sample 4. Batc %ransaction Processing" sample5 "Sample 5. Embedded PL/SQL" sample6 "Sample 6. Calling a Stored Procedure" ou run some samples interactively Irom SQL*Plus, oters Irom Pro*C programs. ou can experiment wit te samples Irom any Oracle account. However, te Pro*C examples expect you to use te 8.ott/tigeraccount. BeIore trying te samples, you must create some database tables, ten load te tables wit data. ou do tat by running two SQL*Plus scripts, exampbld and examplod, wic are supplied wit PL/SQL. ou can Iind tese scripts in te PL/SQL demo directory. %e Iirst script builds te database tables processed by te sample programs. %e second script loads (or reloads) te database tables. %o run te scripts, invoke SQL*Plus, ten issue te Iollowing commands: SQL START exampbld ... SQL START examplod SampIe 1. # Loop %e Iollowing example uses a simple R loop to insert ten rows into a database table. %e values oI a loop index, counter variable, and eiter oI two caracter strings are inserted. Wic string is inserted depends on te value oI te loop index. 3p:t TabIe ot applicable. PL/SQL BIock -- available online in file '8ample1' DECLARE x NUMBER := 100; BEGIN R i IN 1..10 L! I MD(i,2) = 0 THEN -- i i8 even INSERT INT temp VALUES (i, x, 'i i8 even'); ELSE INSERT INT temp VALUES (i, x, 'i i8 odd'); END I; x := x + 100; END L!; CMMIT; END; :tp:t TabIe SQL SELECT RM temp RDER BY .ol1;
NUM_CL1 NUM_CL2 CHAR_CL -------- -------- --------- 1 100 i i8 odd 2 200 i i8 even 3 300 i i8 odd 4 400 i i8 even 5 500 i i8 odd 6 600 i i8 even 7 700 i i8 odd 8 800 i i8 even 9 900 i i8 odd 10 1000 i i8 even SampIe 2. C:rsors %e Iollowing example uses a cursor to select te Iive igest paid employees Irom te emp table. 3p:t TabIe SQL SELECT ename, empno, 8al RM emp RDER BY 8al DESC;
ENAME EM!N SAL ---------- --------- -------- KING 7839 5000 SCTT 7788 3000 RD 7902 3000 JNES 7566 2975 BLAKE 7698 2850 CLARK 7782 2450 ALLEN 7499 1600 TURNER 7844 1500 MILLER 7934 1300 ARD 7521 1250 MARTIN 7654 1250 ADAMS 7876 1100 JAMES 7900 950 SMITH 7369 800 PL/SQL BIock -- available online in file '8ample2' DECLARE CURSR .1 i8 SELECT ename, empno, 8al RM emp RDER BY 8al DESC; -- 8tart with highe8t paid employee my_ename VARCHAR2(10); my_empno NUMBER(4); my_8al NUMBER(7,2); BEGIN !EN .1; R i IN 1..5 L! ETCH .1 INT my_ename, my_empno, my_8al; EXIT HEN .1%NTUND; / in .a8e the number reque8ted / / i8 more than the total / / number of employee8 / INSERT INT temp VALUES (my_8al, my_empno, my_ename); CMMIT; END L!; CLSE .1; END; :tp:t TabIe SQL SELECT RM temp RDER BY .ol1 DESC;
NUM_CL1 NUM_CL2 CHAR_CL -------- -------- -------- 5000 7839 KING 3000 7902 RD 3000 7788 SCTT 2975 7566 JNES 2850 7698 BLAKE SampIe 3. Scop3g %e Iollowing example illustrates block structure and scope rules. n outer block declares two variables named x and .ounter and loops Iour times. Inside tis loop is a sub-block tat also declares a variable named x. %e values inserted into te temp table sow tat te two x's are indeed diIIerent. 3p:t TabIe ot applicable. PL/SQL BIock -- available online in file '8ample3' DECLARE x NUMBER := 0; .ounter NUMBER := 0; BEGIN R i IN 1..4 L! x := x + 1000; .ounter := .ounter + 1; INSERT INT temp VALUES (x, .ounter, 'in UTER loop'); / 8tart an inner blo. / DECLARE x NUMBER := 0; -- thi8 i8 a lo.al ver8ion of x BEGIN R i IN 1..4 L! x := x + 1; -- thi8 in.rement8 the lo.al x .ounter := .ounter + 1; INSERT INT temp VALUES (x, .ounter, 'inner loop'); END L!; END; END L!; CMMIT; END; :tp:t TabIe SQL SELECT RM temp RDER BY .ol2;
NUM_CL1 NUM_CL2 CHAR_CL -------- -------- ------------- 1000 1 in UTER loop 1 2 inner loop 2 3 inner loop 3 4 inner loop 4 5 inner loop 2000 6 in UTER loop 1 7 inner loop 2 8 inner loop 3 9 inner loop 4 10 inner loop 3000 11 in UTER loop 1 12 inner loop 2 13 inner loop 3 14 inner loop 4 15 inner loop 4000 16 in UTER loop 1 17 inner loop 2 18 inner loop 3 19 inner loop 4 20 inner loop SampIe 4. Batch Tra3sacto3 Process3g In te next example te a..ount8 table is modiIied according to instructions stored in te a.tion table. Eac row in te a.tion table contains an account number, an action to be taken (I, U, or D Ior insert, update, or delete), an amount by wic to update te account, and a time tag used to sequence te transactions. On an insert, iI te account already exists, an update is done instead. On an update, iI te account does not exist, it is created by an insert. On a delete, iI te row does not exist, no action is taken. 3p:t TabIes SQL SELECT RM a..ount8 RDER BY a..ount_id;
ACCUNT_ID NE_VALUE STATUS TIME_TAG ---------- - ---------- -------------------- --------- 3 u 599 18-NV-88 6 i 20099 18-NV-88 5 d 18-NV-88 7 u 1599 18-NV-88 1 i 399 18-NV-88 9 d 18-NV-88 10 x 18-NV-88 PL/SQL BIock -- available online in file '8ample4' DECLARE CURSR .1 IS SELECT a..ount_id, oper_type, new_value RM a.tion RDER BY time_tag R U!DATE 8tatu8; BEGIN R a..t IN .1 L! -- pro.e88 ea.h row one at a time
a..t.oper_type := upper(a..t.oper_type);
/----------------------------------------/ / !ro.e88 an U!DATE. If the a..ount to / / be updated doe8n't exi8t, .reate a new / / a..ount. / /----------------------------------------/ I a..t.oper_type = 'U' THEN U!DATE a..ount8 SET bal = a..t.new_value HERE a..ount_id = a..t.a..ount_id;
I SQL%NTUND THEN -- a..ount didn't exi8t. Create it. INSERT INT a..ount8 VALUES (a..t.a..ount_id, a..t.new_value); U!DATE a.tion SET 8tatu8 = 'Update: ID not found. Value in8erted.' HERE CURRENT .1; ELSE U!DATE a.tion SET 8tatu8 = 'Update: Su..e88.' HERE CURRENT .1; END I;
/--------------------------------------------/ / !ro.e88 an INSERT. If the a..ount already / / exi8t8, do an update of the a..ount / / in8tead. / /--------------------------------------------/ ELSI a..t.oper_type = 'I' THEN BEGIN INSERT INT a..ount8 VALUES (a..t.a..ount_id, a..t.new_value); U!DATE a.tion 8et 8tatu8 = 'In8ert: Su..e88.' HERE CURRENT .1; EXCE!TIN HEN DU!_VAL_N_INDEX THEN -- a..ount already exi8t8 U!DATE a..ount8 SET bal = a..t.new_value HERE a..ount_id = a..t.a..ount_id; U!DATE a.tion SET 8tatu8 = 'In8ert: A..t exi8t8. Updated in8tead.' HERE CURRENT .1; END;
/--------------------------------------------/ / !ro.e88 a DELETE. If the a..ount doe8n't / / exi8t, 8et the 8tatu8 field to 8ay that / / the a..ount wa8n't found. / /--------------------------------------------/ ELSI a..t.oper_type = 'D' THEN DELETE RM a..ount8 HERE a..ount_id = a..t.a..ount_id;
I SQL%NTUND THEN -- a..ount didn't exi8t. U!DATE a.tion SET 8tatu8 = 'Delete: ID not found.' HERE CURRENT .1; ELSE U!DATE a.tion SET 8tatu8 = 'Delete: Su..e88.' HERE CURRENT .1; END I;
/--------------------------------------------/ / The reque8ted operation i8 invalid. / /--------------------------------------------/ ELSE -- oper_type i8 invalid U!DATE a.tion SET 8tatu8 = 'Invalid operation. No a.tion taen.' HERE CURRENT .1;
END I;
END L!; CMMIT; END; :tp:t TabIes SQL SELECT RM a..ount8 RDER BY a..ount_id;
ACCUNT_ID NE_VALUE STATUS TIME_TAG ---------- - ---------- --------------------- --------- 3 u 599 Update: Su..e88. 18-NV-88 6 i 20099 In8ert: Su..e88. 18-NV-88 5 d Delete: Su..e88. 18-NV-88 7 u 1599 Update: ID not found. 18-NV-88 Value in8erted. 1 i 399 In8ert: A..t exi8t8. 18-NV-88 Updated in8tead. 9 d Delete: ID not found. 18-NV-88 10 x Invalid operation. 18-NV-88 No a.tion taen. SampIe 5. Embe//e/ PL/SQL %e Iollowing example sows ow you can embed PL/SQL in a ig-level ost language suc as C and demonstrates ow a banking debit transaction migt be done. 3p:t TabIe SQL SELECT RM a..ount8 RDER BY a..ount_id;
ACCUNT_ID BAL ---------- -------- 1 1000 2 2000 3 1500 4 6500 5 500 PL/SQL BIock 3 a C Program / available online in file '8ample5' / #in.lude <8tdio.h .har buf20,; EXEC SQL BEGIN DECLARE SECTIN; int a..t; double debit; double new_bal; VARCHAR 8tatu865,; VARCHAR uid20,; VARCHAR pwd20,; EXEC SQL END DECLARE SECTIN;
printf("\n\n\tEmbedded !L/SQL Debit Tran8a.tion Demo\n\n"); printf("Trying to .onne.t..."); EXEC SQL HENEVER SQLERRR GT errprint; EXEC SQL CNNECT :uid IDENTIIED BY :pwd; printf(" .onne.ted.\n"); for (;;) / Loop infinitely /
printf("\n Debit whi.h a..ount number. (-1 to end) "); get8(buf); a..t = atoi(buf); if (a..t == -1) / Need to di8.onne.t from ra.le / / and exit loop if a..ount i8 -1 / EXEC SQL CMMIT RELEASE; exit(0); ,
printf(" hat i8 the debit amount. "); get8(buf); debit = atof(buf);
/ ---------------------------------- / / ----- Begin the !L/SQL blo. ----- / / ---------------------------------- / EXEC SQL EXECUTE
DECLARE in8uffi.ient_fund8 EXCE!TIN; old_bal NUMBER; min_bal CNSTANT NUMBER := 500; BEGIN SELECT bal INT old_bal RM a..ount8 HERE a..ount_id = :a..t; -- If the a..ount doe8n't exi8t, the N_DATA_UND -- ex.eption will be automati.ally rai8ed. :new_bal := old_bal - :debit; I :new_bal = min_bal THEN U!DATE a..ount8 SET bal = :new_bal HERE a..ount_id = :a..t; INSERT INT journal VALUES (:a..t, 'Debit', :debit, SYSDATE); :8tatu8 := 'Tran8a.tion .ompleted.'; ELSE RAISE in8uffi.ient_fund8; END I; CMMIT; EXCE!TIN HEN N_DATA_UND THEN :8tatu8 := 'A..ount not found.'; :new_bal := -1; HEN in8uffi.ient_fund8 THEN :8tatu8 := 'In8uffi.ient fund8.'; :new_bal := old_bal; HEN THERS THEN RLLBACK; :8tatu8 := 'Error: ' || SQLERRM(SQLCDE); :new_bal := -1; END;
END-EXEC; / -------------------------------- / / ----- End the !L/SQL blo. ----- / / -------------------------------- /
8tatu8.arr8tatu8.len, = '\0'; / null-terminate / / the 8tring / printf("\n\n Statu8: %8\n", 8tatu8.arr); if (new_bal = 0) printf(" Balan.e i8 now: $%.2f\n", new_bal); , / End of loop /
ACCUNT_ID ACTIN AMUNT DATE_TAG ---------- -------------------- --------- --------- 1 Debit 300 28-NV-88 2 Debit 500 28-NV-88 2 Debit 100 28-NV-88 SampIe 6. CaII3g a Store/ Proce/:re %is Pro*C program connects to Oracle, prompts te user Ior a department number, ten calls procedure get_employee8, wic is stored in package per8onnel. %e procedure declares tree index-by tables as UTIormal parameters, ten Ietces a batc oI employee data into te index-by tables. %e matcing actual parameters are ost arrays. Wen te procedure Iinises, it automatically assigns all row values in te index- by tables to corresponding elements in te ost arrays. %e program calls te procedure repeatedly, displaying eac batc oI employee data, until no more data is Iound. 3p:t TabIe SQL SELECT ename, empno, 8al RM emp RDER BY 8al DESC;
ENAME EM!N SAL ---------- --------- -------- KING 7839 5000 SCTT 7788 3000 RD 7902 3000 JNES 7566 2975 BLAKE 7698 2850 CLARK 7782 2450 ALLEN 7499 1600 TURNER 7844 1500 MILLER 7934 1300 ARD 7521 1250 MARTIN 7654 1250 ADAMS 7876 1100 JAMES 7900 950 SMITH 7369 800 Store/ Proce/:re / available online in file '8ample6' / #in.lude <8tdio.h #in.lude <8tring.h
typedef .har a8.iz;
EXEC SQL BEGIN DECLARE SECTIN; / Define type for null-terminated 8tring8. / EXEC SQL TY!E a8.iz IS STRING(20); a8.iz u8ername20,; a8.iz pa88word20,; int dept_no; / whi.h department to query / .har emp_name10,21,; .har job10,21,; EXEC SQL VAR emp_name i8 STRING (21); EXEC SQL VAR job i8 STRING (21); float 8alary10,; int done_flag; int array_8ize; int num_ret; / number of row8 returned / int SQLCDE; EXEC SQL END DECLARE SECTIN;
EXEC SQL INCLUDE 8ql.a;
int print_row8(); / produ.e8 program output / int 8qlerror(); / handle8 unre.overable error8 /
main()
int i;
/ Conne.t to ra.le. / 8tr.py(u8ername, "SCTT"); 8tr.py(pa88word, "TIGER");
EXEC SQL HENEVER SQLERRR D 8qlerror();
EXEC SQL CNNECT :u8ername IDENTIIED BY :pa88word; printf("\nConne.ted to ra.le a8 u8er: %8\n\n", u8ername);
printf("Enter department number: "); 8.anf("%d", &dept_no); fflu8h(8tdin);
B CHA# ;ers:s VA#CHA#2 Sema3tcs %is appendix explains te semantic diIIerences between te CHAR and VARCHAR2 base types. %ese subtle but important diIIerences come into play wen you assign, compare, insert, update, select, or Ietc caracter values. %is appendix discusses te Iollowing topics: sslgnlng CharacLer values Comparlng CharacLer values lnserLlng CharacLer values SelecLlng CharacLer values Assg33g Character VaI:es Wen you assign a caracter value to a CHAR variable, iI te value is sorter tan te
declared lengt oI te variable, PL/SQL blank- pads te value to te declared lengt. So, inIormation about trailing blanks is lost. In te Iollowing example, te value assigned to la8t_name includes six trailing blanks, not just one: la8t_name CHAR(10) := 'CHEN '; -- note trailing blan
II te caracter value is longer tan te declared lengt oI te CHAR variable, PL/SQL aborts te assignment and raises te predeIined exception VALUE_ERRR. PL/SQL neiter truncates te value nor tries to trim trailing blanks. For example, given te declaration a.ronym CHAR(4);
Wen you assign a caracter value to a VARCHAR2 variable, iI te value is sorter tan te declared lengt oI te variable, PL/SQL neiter blank-pads te value nor strips trailing blanks. Caracter values are assigned intact, so no inIormation is lost. II te caracter value is longer tan te declared lengt oI te VARCHAR2 variable, PL/SQL aborts te assignment and raises VALUE_ERRR. PL/SQL neiter truncates te value nor tries to trim trailing blanks. Compar3g Character VaI:es ou can use te relational operators to compare caracter values Ior equality or inequality. Comparisons are based on te collating sequence used Ior te database caracter set. One caracter value is greater tan anoter iI it Iollows it in te collating sequence. For example, given te declarations la8t_name1 VARCHAR2(10) := 'CLES'; la8t_name2 VARCHAR2(10) := 'CLEMAN';
te Iollowing IF condition is true: I la8t_name1 la8t_name2 THEN ...
SI/ISO SQL requires tat two caracter values being compared ave equal lengts. So, iI bot values in a comparison ave datatype CHAR, blank-padding semantics are used. %at is, beIore comparing caracter values oI unequal lengt, PL/SQL blank-pads te sorter value to te lengt oI te longer value. For example, given te declarations la8t_name1 CHAR(5) := 'BELL'; la8t_name2 CHAR(10) := 'BELL '; -- note trailing blan8
te Iollowing I condition is true: I la8t_name1 = la8t_name2 THEN ...
II eiter value in a comparison as datatype VARCHAR2, non-blank- padding semantics are used. %at is, wen comparing caracter values oI unequal lengt, PL/SQL makes no adjustments and uses te exact lengts. For example, given te declarations la8t_name1 VARCHAR2(10) := 'D'; la8t_name2 VARCHAR2(10) := 'D '; -- note trailing blan8
te Iollowing I condition is Ialse: I la8t_name1 = la8t_name2 THEN ...
II one value in a comparison as datatype VARCHAR2 and te oter value as datatype CHAR, non-blank-padding semantics are used. But, remember, wen you assign a caracter value to a CHAR variable, iI te value is sorter tan te declared lengt oI te variable, PL/SQL blank-pads te value to te declared lengt. So, given te declarations la8t_name1 VARCHAR2(10) := 'STAUB'; la8t_name2 CHAR(10) := 'STAUB'; -- !L/SQL blan-pad8 value
te Iollowing I condition is Ialse because te value oI la8t_name2 includes Iive trailing blanks: I la8t_name1 = la8t_name2 THEN ...
ll string literals ave datatype CHAR. So, iI bot values in a comparison are literals, blank- padding semantics are used. II one value is a literal, blank-padding semantics are used only iI te oter value as datatype CHAR. 3sert3g Character VaI:es Wen you insert te value oI a PL/SQL caracter variable into an Oracle database column, weter te value is blank-padded or not depends on te column type, not on te variable type. Wen you insert a caracter value into a CHAR database column, Oracle does not strip trailing blanks. II te value is sorter tan te deIined widt oI te column, Oracle blank- pads te value to te deIined widt. s a result, inIormation about trailing blanks is lost. II te caracter value is longer tan te deIined widt oI te column, Oracle aborts te insert and generates an error. Wen you insert a caracter value into a VARCHAR2 database column, Oracle does not strip trailing blanks. II te value is sorter tan te deIined widt oI te column, Oracle does not blank-pad te value. Caracter values are stored intact, so no inIormation is lost. II te caracter value is longer tan te deIined widt oI te column, Oracle aborts te insert and generates an error. 490 %e same rules apply wen updating. Wen inserting caracter values, to ensure tat no trailing blanks are stored, use te Iunction RTRIM, wic trims trailing blanks. n example Iollows: DECLARE ... my_name VARCHAR2(15); BEGIN ... my_ename := 'LEE '; -- note trailing blan8 INSERT INT emp VALUES (my_empno, RTRIM(my_ename), ...); -- in8ert8 'LEE' END; SeIect3g Character VaI:es Wen you select a value Irom an Oracle database column into a PL/SQL caracter variable, weter te value is blank-padded or not depends on te variable type, not on te column type. Wen you select a column value into a CHAR variable, iI te value is sorter tan te declared lengt oI te variable, PL/SQL blank- pads te value to te declared lengt. s a result, inIormation about trailing blanks is lost. II te caracter value is longer tan te declared lengt oI te variable, PL/SQL aborts te assignment and raises VALUE_ERRR. Wen you select a column value into a VARCHAR2 variable, iI te value is sorter tan te declared lengt oI te variable, PL/SQL neiter blank-pads te value nor strips trailing blanks. Caracter values are stored intact, so no inIormation is lost. For example, wen you select a blank- padded CHAR column value into a VARCHAR2 variable, te trailing blanks are not stripped. II te caracter value is longer tan te declared lengt oI te VARCHAR2 variable, PL/SQL aborts te assignment and raises VALUE_ERRR. 490 %e same rules apply wen Ietcing.