datubaze.files.wordpress.com  · Web viewŅemot vērā to, ka PL/SQL ir tik cieši integrēts ar...

24
Steven Feuerstein. Bulk Processing with BULK COLLECT and FORALL. September/October 2012 1 Lielapjoma datu izgūšanā divas svarīgākās veiktspējas optimizācijas iespējas ir BULK COLLECT un FORALL: 1) BULK COLLECT izgūt vairākas rindas ar vienu ienesi (fetch), uzlabojot datu izgūšanas ātrumu; 2) FORALL izmanto INSERT, UPDATE un DELETE komandās, kas izmanto kolekcijas, lai ļoti ātri apstrādātu vairākas datu rindas. Cik liela ir šo iespēju ietekme? Rezultāti atšķirsies atkarībā no jūsu izmantotās datu bāzes versijas un lietojumprogrammas loģikas specifikas. Skriptu var lejupielādēt un palaist, lai salīdzinātu iespraušanas pēc rindas veiktspēju ar FORALL iespraušanu. Klēpjdatorā, kurā darbojas Oracle Database 11 g2. versija, 100 000 rindu ievietošanai bija nepieciešamas 4,94 sekundes, pa vienai. Ar FORALL šie 100 000 tika ievietoti 0.12 sekundēs. Ņemot vērā to, ka PL/SQL ir tik cieši integrēts ar SQL valodu, jūs varētu uzzināt, kāpēc būtu nepieciešami īpaši līdzekļi, lai uzlabotu SQL priekšrakstu veiktspēju PL/SQL. Izskaidrojums ir saistīts ar to, kā gan PL/SQL, gan SQL izpildlaika dzinēji sazinās ar citiem, izmantojot konteksta slēdzi. 1 https://blogs.oracle.com/oraclemagazine/bulk-processing-with-bulk- collect-and-forall

Transcript of datubaze.files.wordpress.com  · Web viewŅemot vērā to, ka PL/SQL ir tik cieši integrēts ar...

Page 1: datubaze.files.wordpress.com  · Web viewŅemot vērā to, ka PL/SQL ir tik cieši integrēts ar SQL valodu, jūs varētu uzzināt, kāpēc būtu nepieciešami īpaši līdzekļi,

Steven Feuerstein. Bulk Processing with BULK COLLECT and FORALL. September/October 20121

Lielapjoma datu izgūšanā divas svarīgākās veiktspējas optimizācijas iespējas ir BULK COLLECT un FORALL:

1) BULK COLLECT izgūt vairākas rindas ar vienu ienesi (fetch), uzlabojot datu izgūšanas ātrumu;

2) FORALL izmanto INSERT, UPDATE un DELETE komandās, kas izmanto kolekcijas, lai ļoti ātri apstrādātu vairākas datu rindas.

Cik liela ir šo iespēju ietekme? Rezultāti atšķirsies atkarībā no jūsu izmantotās datu bāzes versijas un lietojumprogrammas loģikas specifikas. Skriptu var lejupielādēt un palaist, lai salīdzinātu iespraušanas pēc rindas veiktspēju ar FORALL iespraušanu. Klēpjdatorā, kurā darbojas Oracle Database 11 g2. versija, 100 000 rindu ievietošanai bija nepieciešamas 4,94 sekundes, pa vienai. Ar FORALL šie 100 000 tika ievietoti 0.12 sekundēs. Ņemot vērā to, ka PL/SQL ir tik cieši integrēts ar SQL valodu, jūs varētu uzzināt, kāpēc būtu nepieciešami īpaši līdzekļi, lai uzlabotu SQL priekšrakstu veiktspēju PL/SQL. Izskaidrojums ir saistīts ar to, kā gan PL/SQL, gan SQL izpildlaika dzinēji sazinās ar citiem, izmantojot konteksta slēdzi.

1 https://blogs.oracle.com/oraclemagazine/bulk-processing-with-bulk-collect-and-forall

Page 2: datubaze.files.wordpress.com  · Web viewŅemot vērā to, ka PL/SQL ir tik cieši integrēts ar SQL valodu, jūs varētu uzzināt, kāpēc būtu nepieciešami īpaši līdzekļi,

Kontekstslēdži un veiktspēja

Gandrīz katrā programmas PL/SQL izstrādātāju rakstā ir iekļauti gan PL/SQL, gan SQL priekšraksti. PL/SQL priekšrakstus izpilda PL/SQL priekšrakstu izpildītājs; SQL priekšrakstus izpilda SQL priekšrakstu izpildītājs. Kad PL/SQL izpildlaika programma saskaras ar SQL priekšrakstu, tas tiek apturēts un pārnes SQL priekšrakstu uz SQL dzinēju. SQL dzinējs izpilda SQL priekšrakstu un atgriež informāciju atpakaļ PL/SQL dzinējam (attēls). Šī vadības pārraide tiek saukta par konteksta slēdzi, un katrs no šiem slēdžiem veido pieskaitamās izmaksas (incurs overhead), kas palēnina programmu vispārējo veiktspēju.

Page 3: datubaze.files.wordpress.com  · Web viewŅemot vērā to, ka PL/SQL ir tik cieši integrēts ar SQL valodu, jūs varētu uzzināt, kāpēc būtu nepieciešami īpaši līdzekļi,

BULK COLLECT komandas izmantošana DB tabulas rakstu nolasīšanai

declaretype TAB_TIPS is table of FIRMAS%ROWTYPE; tab TAB_TIPS := TAB_TIPS();

i number;begin

select * BULK COLLECT into tab from FIRMAS; for i in 1 ..3 loop DBMS_OUTPUT.PUT_LINE(tab(i).F_NOS);end loop; end;

BBBCCCAAA

Notiek automātika tabulas rindu inicializācija (EXTEND)!

tab1 BBB 2005-FEB-152 CCC 2006-JAN-233 AAA 2007-DEC-6

FIRMASF_NUM F_NO

SDIBIN_DAT

1 BBB 2005-FEB-152 CCC 2006-JAN-233 AAA 2007-DEC-6

Page 4: datubaze.files.wordpress.com  · Web viewŅemot vērā to, ka PL/SQL ir tik cieši integrēts ar SQL valodu, jūs varētu uzzināt, kāpēc būtu nepieciešami īpaši līdzekļi,

Algas palielināšanas procedūras variantu analīzeAplūkosim piemēru, lai izpētītu konteksta slēdžus, kas pārslēdzas pamatīgāk(thoroughly), un noskaidrosim iemeslu, kāpēc FORALL un BULK COLLECT var būt tik dramatiska ietekme uz veiktspēju.Pieņemsim, ka jāuzraksta procedūra, kas pieņem nodaļas ID un algas procentu palielinājumu, un dod iespēju visiem šajā nodaļā strādājošajiem palielināt algu par norādītajiem procentiem. Izmantojot PL/SQL kursoru ciklu FOR loop un iespēju PL/SQL lietot SQL priekšrakstus, tiek izveidots šāds kods:

create table DARBINIEKI (DARB_ID number,NOD_ID number,ALGA number(8,2));

begininsert into DARBINIEKI values (101, 1, 800);insert into DARBINIEKI values (102, 1, 900);insert into DARBINIEKI values (103, 1, 700);insert into DARBINIEKI values (104, 2, 1000);insert into DARBINIEKI values (105, 2, 1000);insert into DARBINIEKI values (106, 2, 1000);insert into DARBINIEKI values (107, 2, 1000);insert into DARBINIEKI values (108, 2, 1000);insert into DARBINIEKI values (109, 2, 1000);insert into DARBINIEKI values (110, 2, 1000);insert into DARBINIEKI values (111, 2, 1000);insert into DARBINIEKI values (112, 2, 1000);insert into DARBINIEKI values (113, 2, 1000);insert into DARBINIEKI values (114, 2, 1000);end;

Page 5: datubaze.files.wordpress.com  · Web viewŅemot vērā to, ka PL/SQL ir tik cieši integrēts ar SQL valodu, jūs varētu uzzināt, kāpēc būtu nepieciešami īpaši līdzekļi,

Vienkārša algas palielināšanas procedūra ar ciklu un UPDATE komandu

create or replace procedure ALGAS_PALIELINASANA (nod_id_in IN number, palielinajums_proc_in IN number) isbeginFOR raksts_darbinieks in (select DARB_ID, NOD_ID, ALGA from DARBINIEKI where NOD_ID = nod_id_in) loop update DARBINIEKI a set a.ALGA = a.ALGA + a.ALGA * palielinajums_proc_in where a.DARB_ID = raksts_darbinieks.DARB_ID;end loop;end ALGAS_PALIELINASANA;

begin ALGAS_PALIELINASANA (2, 10);end;

Page 6: datubaze.files.wordpress.com  · Web viewŅemot vērā to, ka PL/SQL ir tik cieši integrēts ar SQL valodu, jūs varētu uzzināt, kāpēc būtu nepieciešami īpaši līdzekļi,

Algas palielināšanas procedūra bez cikla FOR

Iepriekšējā piemērā PL/SQL dzinējs pārslēdzas uz SQL dzinēju daudzas reizes (katrai rindai, kas tiek atjaunināta). Tom Kyte (asktom.oracle.com), norāda, ka šāda veida pārslēgšanās pa rindai ir “lēna un lēna apstrāde”, un tas noteikti ir kaut kas, no kā ir jāizvairās.Vispirms vienmēr pārbaudiet, vai nav iespējams izvairīties no konteksta maiņas starp PL/SQL un SQL, veicot pēc iespējas vairāk darba SQL.

create or replace procedure ALGAS_PALIELINASANA (nod_id_in IN number, palielinajums_proc_in IN number) isbeginupdate DARBINIEKI a set a.ALGA = a.ALGA + a.ALGA * palielinajums_proc_in where a.NOD_ID = nod_id_in;end ALGAS_PALIELINASANA;

Tagad ir tikai viena konteksta pārslēgšana, lai izpildītu vienu UPDATE priekšrakstu. Viss darbs tiek veikts SQL dzinējā.

Page 7: datubaze.files.wordpress.com  · Web viewŅemot vērā to, ka PL/SQL ir tik cieši integrēts ar SQL valodu, jūs varētu uzzināt, kāpēc būtu nepieciešami īpaši līdzekļi,

Algas palielināšanas procedūra ar Bulk COLLECT un FORALLPL/SQL lielapjoma apstrādes līdzekļi ir īpaši izstrādāti, lai samazinātu kontekstslēdžu skaitu, kas nepieciešams, lai sazinātos ar PL/SQL dzinēju un SQL dzinēju.Izmantojiet BULK COLLECT klauzulu, lai ienestu vairākas rindas vienā vai vairākās kolekcijās ar vienu konteksta slēdzi.Izmantojiet priekšrakstu FORALL, ja nepieciešams atkārtoti izpildīt vienu un to pašu DML priekšrakstu dažādām saistījuma mainīgajām vērtībām. UPDATE priekšraksts ALGAS_PALIELINASANA procedūrā atbilst šim scenārijam. Vienīgais, kas mainās līdz ar katru jaunu priekšraksta izpildi, ir darbinieka ID.

create or replace procedure ALGAS_PALIELINASANA (nod_id_in IN DARBINIEKI.NOD_ID%TYPE,pieaugums IN number) istype darb_id_tips is TABLE of DARBINIEKI.DARB_ID%TYPEINDEX BY PLS_INTEGER; tabula darb_id_tips;beginselect DARB_ID BULK COLLECT INTO tabulafrom DARBINIEKIWHERE NOD_ID = nod_id_in;

FORALL i in 1 .. tabula.COUNTupdate DARBINIEKI a SET a.ALGA = a.ALGA + a.ALGA * pieaugumswhere a.DARB_ID = tabula(i);end ALGAS_PALIELINASANA;

beginALGAS_PALIELINASANA(1, 0.2); end;

Ir trīs izpildes posmi:1. Ienest rindas ar BULK COLLECT vienā vai vairākās kolekcijās. Šim solim ir nepieciešama viens konteksta slēdzis.2. Pēc nepieciešamības modificējiet kolekciju saturu (piemēram, noņemot nepiemērotos darbiniekus).3. Mainiet tabulu, izmantojot FORALL kolekcijas.

Page 8: datubaze.files.wordpress.com  · Web viewŅemot vērā to, ka PL/SQL ir tik cieši integrēts ar SQL valodu, jūs varētu uzzināt, kāpēc būtu nepieciešami īpaši līdzekļi,

Tā vietā, lai pārvietotos uz priekšu un atpakaļ starp PL/SQL un SQL dzinējiem, lai atjauninātu katru rindu, FORALL atjauninājumi tiek “sasaistīti” un tiek nodoti SQL dzinējam ar vienu konteksta slēdzi. Rezultāts ir ārkārtējs veiktspējas pieaugums.

Page 9: datubaze.files.wordpress.com  · Web viewŅemot vērā to, ka PL/SQL ir tik cieši integrēts ar SQL valodu, jūs varētu uzzināt, kāpēc būtu nepieciešami īpaši līdzekļi,

BULK COLLECT izmantošana divām kolonām

Lai izmantotu vaicājumu lielapjoma apstrādes priekšrocības, jūs vienkārši ievietojat BULK COLLECT pirms INTO un pēc tam norādāt vienu vai vairākas kolekcijas pēc INTO atslēgvārda.

BULK COLLECT var izmantot visu triju veidu kolekcijām: asociatīviem masīviem, ligzdtabulām un VARRAYs.

Varat ienest atsevišķās kolekcijās (vienu katrai izteiksmei SELECT sarakstā) vai vienā ierakstu kolekcijā.Kolekcija vienmēr tiek aizpildīta blīvi, sākot ar indeksa vērtību 1.Ja netiek ienestas rindas, kolekcija tiek iztukšota no visiem elementiem.

declaretype raksts_2_kol is RECORD ( darbin_id DARBINIEKI.DARB_ID%TYPE, alga DARBINIEKI.ALGA%TYPE);

type tips_darb_tab is TABLE of raksts_2_kol;tab_darb tips_darb_tab;begin select DARB_ID, ALGA BULK COLLECT INTO tab_darb from DARBINIEKIwhere NOD_ID = 2;end;

Page 10: datubaze.files.wordpress.com  · Web viewŅemot vērā to, ka PL/SQL ir tik cieši integrēts ar SQL valodu, jūs varētu uzzināt, kāpēc būtu nepieciešami īpaši līdzekļi,

BULK COLLECT izmantošana divām kolonāmIenesot programmā daudz rindu, piepildītā kolekcija var patērēt pārāk daudz sesijas atmiņas un izraisīt kļūdu. Lai palīdzētu izvairīties no šādām kļūdām, Oracle Database piedāvā BULK COLLECT ierobežojuma klauzulu LIMIT. Pieņemsim, ka, piemēram, vienā nodaļā varētu būt desmitiem tūkstošu darbinieku un manai sesijai nepietiek atmiņas, lai kolekcijā saglabātu 20 000 darbinieku ID.Tā vietā var izmantot šādu programmu:

declarec_limits PLS_INTEGER := 100;cursor KURS_DARB is select DARB_ID from DARBINIEKI where NOD_ID = nod_id_in;

type tips_tab_darb is TABLE of DARBINIEKI.DARB_ID%TYPE;tab_darb tips_tab_darb;beginopen KURS_DARBIN;

loopfetch KURS_DARB BULK COLLECT INTO tab_darb LIMIT c_limits;EXIT WHEN tab_darb.COUNT = 0;end loop;end;

Izmantojot šo pieeju, tiek atvērts kursors, kas identificē visas rindas, kuras nepieciešams iegūt. Pēc tam cikla iekšpusē tiek izmantots FETCH-BULK COLLECT-INTO, lai sasniegtu c_limits konstantes norādīto rindu skaitu (iestatīts uz 100). Tagad, lai cik daudz rindu man būtu nepieciešams, mana sesija nekad nepatērēs vairāk atmiņas, nekā nepieciešams šīm 100 rindām, tomēr es joprojām gūšu labumu no lielapjoma vaicājumu veiktspējas uzlabošanas.

Page 11: datubaze.files.wordpress.com  · Web viewŅemot vērā to, ka PL/SQL ir tik cieši integrēts ar SQL valodu, jūs varētu uzzināt, kāpēc būtu nepieciešami īpaši līdzekļi,

FORALL izmantošanaJa cikla iekšpusē izpildāt DML priekšrakstu, šis kods ir jākonvertē izmantojot FORALL. Veiktspējas uzlabojums būs ļoti būtisks.FORALL priekšraksts nav cikls. Tas ir deklaratīvs paziņojums PL/SQL dzinējam: “Izveidojiet visus DML priekšrakstus, kas būtu izpildīti pa vienai rindai, un nosūtiet tos visus uz SQL dzinēju ar vienu konteksta slēdzi.”

Lūk, dažas lietas, kas jāzina par FORALL:1) katrs FORALL var saturēt tikai vienu DML priekšrakstu. Ja cilpa satur divus atjauninājumus un

dzēšanu, jums ir jāraksta trīs FORALL.2) PL/SQL deklarē FORALL iteratoru kā veselu skaitli, tāpat kā tas tiek FOR ciklā. Jums nav

nepieciešams declarēt mainīgo ar tādu pašu nosaukumu.3) DML priekšrakstā vismaz vienā vietā ir jānorāda kolekcija un jāizmanto FORALL iteratoru kā

indeksa vērtību šajā kolekcijā;4) izmantojot vērtību IN min .. max sintaksi pašā FORALL virsrakstā, kolekcijas, uz kurām ir

atsauce priekšrakstā ir jāaizpilda blīvi. Jādefinē katra indeksa vērtība starp min un max.5) ja jūsu kolekcija nav blīvi aizpildīta, izmantojiet sintakses INDICES OF vai VALUES OF

FORALL virsrakstā.

Page 12: datubaze.files.wordpress.com  · Web viewŅemot vērā to, ka PL/SQL ir tik cieši integrēts ar SQL valodu, jūs varētu uzzināt, kāpēc būtu nepieciešami īpaši līdzekļi,

FORALL and DML Errors

Suppose that I’ve written a program that is supposed to insert 10,000 rows into a table. After inserting 9,000 of those rows, the 9,001st insert fails with a DUP_VAL_ON_INDEX error (a unique index violation). The SQL engine passes that error back to the PL/SQL engine, and if the FORALL statement is written like the one in Listing 4, PL/SQL will terminate the FORALL statement. The remaining 999 rows will not be inserted.If you want the PL/SQL engine to execute as many of the DML statements as possible, even if errors are raised along the way, add the SAVE EXCEPTIONS clause to the FORALL header. Then, if the SQL engine raises an error, the PL/SQL engine will save that information in a pseudocollection named SQL%BULK_EXCEPTIONS, and continue executing statements. When all statements have been attempted, PL/SQL then raises the ORA-24381 error.You can—and should—trap that error in the exception section and then iterate through the contents of SQL%BULK_EXCEPTIONS to find out which errors have occurred. You can then write error information to a log table and/or attempt recovery of the DML statement.Listing 7 contains an example of using SAVE EXCEPTIONS in a FORALL statement; in this case, I simply display on the screen the index in the l_eligible_ids collection on which the error occurred, and the error code that was raised by the SQL engine.Code Listing 7: Using SAVE EXCEPTIONS with FORALLBEGIN FORALL indx IN 1 .. l_eligible_ids.COUNT SAVE EXCEPTIONS UPDATE employees emp SET emp.salary = emp.salary + emp.salary * increase_pct_in WHERE emp.employee_id = l_eligible_ids (indx);EXCEPTION WHEN OTHERS THEN IF SQLCODE = -24381 THEN FOR indx IN 1 .. SQL%BULK_EXCEPTIONS.COUNT LOOP DBMS_OUTPUT.put_line ( SQL%BULK_EXCEPTIONS (indx).ERROR_INDEX || ‘: ‘ || SQL%BULK_EXCEPTIONS (indx).ERROR_CODE); END LOOP; ELSE RAISE; END IF;END increase_salary;

Page 13: datubaze.files.wordpress.com  · Web viewŅemot vērā to, ka PL/SQL ir tik cieši integrēts ar SQL valodu, jūs varētu uzzināt, kāpēc būtu nepieciešami īpaši līdzekļi,

No SQL uz PL/SQL

This article talks mostly about the context switch from the PL/SQL engine to the SQL engine that occurs when a SQL statement is executed from within a PL/SQL block. It is important to remember that a context switch also takes place when a user-defined PL/SQL function is invoked from within an SQL statement.Suppose that I have written a function named betwnstr that returns the string between a start and end point. Here’s the header of the function:

FUNCTION betwnstr ( string_in IN VARCHAR2 , start_in IN INTEGER , end_in IN INTEGER) RETURN VARCHAR2

I can then call this function as follows:

SELECT betwnstr (last_name, 2, 6) FROM employees WHERE department_id = 10

If the employees table has 100 rows and 20 of those have department_id set to 10, then there will be 20 context switches from SQL to PL/SQL to run this function.You should, consequently, play close attention to all invocations of user-defined functions in SQL, especially those that occur in the WHERE clause of the statement. Consider the following query:

SELECT employee_id FROM employees WHERE betwnstr (last_name, 2, 6) = 'MITHY'

In this query, the betwnstr function will be executed 100 times and there will be 100 context switches.

Page 14: datubaze.files.wordpress.com  · Web viewŅemot vērā to, ka PL/SQL ir tik cieši integrēts ar SQL valodu, jūs varētu uzzināt, kāpēc būtu nepieciešami īpaši līdzekļi,

FORALL with Sparse Collections If you try to use the IN low_value .. high_value syntax with FORALL and there is an undefined index value within that range, Oracle Database will raise the “ORA-22160: element at index [N] does not exist” error.To avoid this error, you can use the INDICES OF or VALUES OF clauses. To see how these clauses can be used, let’s go back to the code in Listing 4. In this version of increase_salary, I declare a second collection, l_eligible_ids, to hold the IDs of those employees who are eligible for a raise.Instead of doing that, I can simply remove all ineligible IDs from the l_employee_ids collection, as follows: FOR indx IN 1 .. l_employee_ids.COUNT LOOP check_eligibility (l_employee_ids (indx), increase_pct_in, l_eligible);

IF NOT l_eligible THEN l_employee_ids.delete (indx); END IF; END LOOP;But now my l_employee_ids collection may have gaps in it: index values that are undefined between 1 and the highest index value populated by the BULK COLLECT.No worries. I will simply change my FORALL statement to the following:FORALL indx IN INDICES OF l_employee_ids UPDATE employees emp SET emp.salary = emp.salary + emp.salary * increase_salary.increase_pct_in WHERE emp.employee_id = l_employee_ids (indx);Now I am telling the PL/SQL engine to use only those index values that are defined in l_employee_ids, rather than specifying a fixed range of values. Oracle Database will simply skip any undefined index values, and the ORA-22160 error will not be raised.This is the simplest application of INDICES OF. Check the documentation for more-complex usages of INDICES OF, as well as when and how to use VALUES OF.Bulk Up Your Code! Optimizing the performance of your code can be a difficult and time-consuming task. It can also be a relatively easy and exhilarating experience—if your code has not yet been

Page 15: datubaze.files.wordpress.com  · Web viewŅemot vērā to, ka PL/SQL ir tik cieši integrēts ar SQL valodu, jūs varētu uzzināt, kāpēc būtu nepieciešami īpaši līdzekļi,

modified to take advantage of BULK COLLECT and FORALL. In that case, you have some low-hanging fruit to pick!Take the Challenge Each PL/SQL 101 article offers a quiz to test your knowledge of the information provided in it. The quiz appears below and also at PL/SQL Challenge, a Website that offers online quizzes on the PL/SQL language as well as SQL and Oracle Application Express.I create and populate my employees table as follows:CREATE TABLE plch_employees( employee_id INTEGER, last_name VARCHAR2 (100))/

BEGIN INSERT INTO plch_employees VALUES (100, ‘Picasso’);

INSERT INTO plch_employees VALUES (200, ‘Mondrian’);

INSERT INTO plch_employees VALUES (300, ‘O’’Keefe’);

COMMIT;END;/QuestionWhich of these blocks will uppercase the last names of all employees in the table?a. DECLARE TYPE ids_t IS TABLE OF plch_employees.employee_id%TYPE;

l_ids ids_t := ids_t (100, 200, 300);BEGIN FORALL indx IN 1 .. l_ids.COUNT LOOP UPDATE plch_employees SET last_name = UPPER (last_name) WHERE employee_id = l_ids (indx);

Page 16: datubaze.files.wordpress.com  · Web viewŅemot vērā to, ka PL/SQL ir tik cieši integrēts ar SQL valodu, jūs varētu uzzināt, kāpēc būtu nepieciešami īpaši līdzekļi,

END LOOP; END;/

b. DECLARE TYPE ids_t IS TABLE OF plch_employees.employee_id%TYPE;

l_ids ids_t := ids_t (100, 200, 300);BEGIN FORALL indx IN 1 .. l_ids.COUNT UPDATE plch_employees SET last_name = UPPER (last_name) WHERE employee_id = l_ids (indx);END;/c. BEGIN UPDATE plch_employees SET last_name = UPPER (last_name);END;/d.DECLARE TYPE ids_t IS TABLE OF plch_employees.employee_id%TYPE;

l_ids ids_t := ids_t (100, 200, 300);BEGIN FORALL indx IN INDICES OF l_ids UPDATE plch_employees SET last_name = UPPER (last_name) WHERE employee_id = l_ids (indx);END;/Answer to the Challenge The PL/SQL Challenge question in last issue’s “Working with Collections” article tested your knowledge of iterating through the contents of a sparsely populated collection. Choice (c) is the only correct choice, and offers the simplest algorithm for accomplishing this task:DECLARE l_names DBMS_UTILITY.maxname_array;

Page 17: datubaze.files.wordpress.com  · Web viewŅemot vērā to, ka PL/SQL ir tik cieši integrēts ar SQL valodu, jūs varētu uzzināt, kāpēc būtu nepieciešami īpaši līdzekļi,

BEGIN l_names (1) := ‘Strawberry’; l_names (10) := ‘Blackberry’; l_names (2) := ‘Raspberry’;

DECLARE indx PLS_INTEGER := l_names.FIRST; BEGIN

WHILE (indx IS NOT NULL) LOOP DBMS_OUTPUT.put_line (l_names (indx)); indx := l_names.NEXT (indx); END LOOP; END;END;/

Steven Feuerstein is Oracle Corporation's Developer Advocate for PL/SQL, and an expert on the Oracle PL/SQL language, having written ten books on PL/SQL, including Oracle PL/SQL Programming and Oracle PL/SQL Best Practices (all...