Own PL/SQL Procedures/Functions (ex7) Write a function which decides if the parameter number is prime or not. In case of yes/no the function returns 1/0. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 CREATE OR REPLACE FUNCTION prim(n integer) RETURN NUMBER IS BEGIN FOR i IN 2..n/2 LOOP IF mod(n,i) = 0 THEN return 0; END IF; END LOOP; RETURN 1; END; / select prim(3) from dual; Write a procedure which prints out the n-th Fibonacchi number. fib1 = 0, fib2 = 1, fib3 = 1, fib4 = 2 ... stb. 1 CREATE OR REPLACE PROCEDURE fib(n integer) 2 IS 3 v1 integer := 0; 4 v2 integer := 1; 5 v_next integer; 6 BEGIN 7 8 IF n <= 1 THEN 9 v_next := v1; 10 ELSIF n = 2 THEN 11 v_next := v2; 12 END IF; 13 14 FOR i IN 3..n LOOP 15 v_next := v1+v2; 16 v1 := v2; 17 v2 := v_next; 18 END LOOP; 19 20 DBMS_OUTPUT.PUT_LINE(TO_CHAR(v_next)); 21 22 23 24 END; / call fib(10); Write a function which returns the greatest common divisor of two integers 1 CREATE OR REPLACE FUNCTION gcd(p1 integer, p2 integer) 2 RETURN number 3 IS 4 BEGIN 5 IF p1 = p2 THEN 6 return p1; 7 END IF; 8 IF p1 = 0 OR p2 = 0 THEN 9 return p1+p2; 10 END IF; 11 12 return gcd(p2, mod(p1,p2)); 13 END; 14 / 15 SELECT gcd(7293,3570) FROM dual; Write a function which returns n factorial. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 /* Write a function which returns n factorial. */ create or replace FUNCTION factor(n integer) RETURN integer IS v_numby integer := 1; too_low EXCEPTION; PRAGMA EXCEPTION_INIT(too_low, -3001); BEGIN IF n < 0 THEN RAISE too_low; END IF; FOR i IN 1..n LOOP v_numby := v_numby * i; END LOOP; RETURN v_numby; END; / select factor(10) from dual; Write a function which returns the number of times the first string parameter contains the second string parameter. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 create or replace FUNCTION num_times(p1 varchar2, p2 varchar2) RETURN integer IS v_position integer; v_position2 integer; v_stringy varchar2(40) := p1; v_count integer := 0; BEGIN FOR i IN 1..length(p1) LOOP v_position := instr(v_stringy, p2) + length(p2); v_position2 := instr(v_stringy,p2); IF v_position2 > 0 THEN v_count := v_count+1; END IF; v_stringy := substr(v_stringy, v_position); END LOOP; return v_count; END; / SELECT num_times ('ab c ab ab de ab fgaaa', 'a') FROM dual; OR 1 create or replace FUNCTION num_times2(p1 VARCHAR2, p2 VARCHAR2) RETURN integer IS 2 BEGIN 3 return REGEXP_COUNT(p1,p2); 4 END; Write a function which returns the sum of the numbers in its string parameter. The numbers are separated with a '+'. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 create or replace FUNCTION sum_of (p_char VARCHAR2) /* Write a function which returns the sum of the numbers in its string parameter. The numbers are separated with a '+'. */ RETURN number IS v_sum integer := 0; v_stringcopy varchar(50) := p_char; v_plusposition integer := instr(p_char, '+'); v_substring varchar(50); BEGIN WHILE length(v_stringcopy) > 0 LOOP IF v_plusposition = 0 THEN EXIT; END IF; 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 v_substring := substr(v_stringcopy, 1, v_plusposition-1); Dbms_Output.Put_Line('substring: ' || v_substring ); v_sum := v_sum + to_number(v_substring); Dbms_Output.Put_Line('sum: ' || v_sum ); v_stringcopy := substr(v_stringcopy, v_plusposition+1); Dbms_Output.Put_Line('stringcopy : ' || v_stringcopy ); v_plusposition := instr(v_stringcopy, '+'); END LOOP; RETURN v_sum; END; / Set Serveroutput On SELECT sum_of('1 + 4 + 13 + 0') FROM dual; Ex9 Write a function which returns the average salary within a salary category (parameter). Can switch between either v_empsal or 1 CREATE OR REPLACE FUNCTION cat_avg(categ integer) 2 RETURN number 3 IS 4 v_avg integer; 5 v_empsals emp.sal%TYPE; 6 7 BEGIN 8 SELECT avg(sal) into v_avg 9 from emp, sal_cat 10 where sal between lowest_sal and highest_sal 11 and category = categ; 12 13 return v_avg; 14 END; 15 / 16 SELECT cat_avg(2) FROM dual; Write a procedure which prints out the number of employees and average salary of the employees whose hiredate was the day which is the parameter of the procedure (e.g. 'Monday'). 1 CREATE OR REPLACE PROCEDURE day_avg(d varchar2) 2 IS 3 4 v_count integer; 5 v_avg emp.sal%TYPE; 6 7 8 9 10 11 12 13 14 15 16 BEGIN select count(*), avg(sal) into v_count, v_avg from emp where to_char(hiredate, 'fmDay','nls_date_language=english') = d; DBMS_OUTPUT.PUT_LINE('avger = ' || TO_CHAR(v_avg) || ' counter = ' || v_count); END; / set Serveroutput On call day_avg('Thursday'); Cursor Write a procedure which takes the employees working on the parameter department in alphabetical order, and prints out the jobs of the employees in a concatenated string. 1 CREATE OR REPLACE PROCEDURE jobs(d_name varchar2) 2 IS 3 v_job emp.job%TYPE; 4 v_toConcat varchar2(50); 5 6 CURSOR cur_job IS 7 SELECT job from emp, dept 8 where emp.deptno = dept.deptno 9 and dname = d_name 10 order by job; 11 12 BEGIN 13 OPEN cur_job; 14 FETCH cur_job INTO v_job; 15 v_toConcat := v_job; 16 LOOP 17 FETCH cur_job INTO v_job; 18 EXIT WHEN cur_job%NOTFOUND; 19 v_toConcat := v_toConcat || ' - ' || v_job; 20 21 END LOOP; 22 DBMS_OUTPUT.PUT_LINE(v_toConcat); 23 CLOSE cur_job; 24 END; 25 / 26 set serveroutput on 27 call jobs('ACCOUNTING'); -- output example: CLERK-ANALYST-SALESMAN Associative array Write a procedure which takes the first n (n is the parameter) prime numbers and puts them into an associative array. The procedure should print out the last prime and the total sum of the numbers. Works but below is probably better Actually this version is the proper one as there was something wrong 1 create or replace PROCEDURE primes(n integer) 2 --ASSOCIATIVE ARRAY EXAMPLE 3 IS 4 5 TYPE tab_type IS TABLE OF NUMBER --Define type of associative array 6 INDEX BY PLS_INTEGER; --How its indexed 7 8 stuff tab_type; --Declare an associative array of the type defined above 9 counter integer := 0; 10 summedprimes integer := 0; 11 12 BEGIN 13 FOR i in 2..n LOOP 14 IF prim(i) > 0 THEN 15 stuff(counter) := i; 16 counter := counter+1; 17 END IF; 18 END LOOP; 19 20 DBMS_OUTPUT.PUT_LINE('The last Prime is: ' || stuff(stuff.LAST)); 21 22 23 FOR i in stuff.FIRST..stuff.LAST LOOP 24 summedprimes := summedprimes + stuff(i); 25 END LOOP; 26 DBMS_OUTPUT.PUT_LINE('Sum of Primes ' || summedprimes); 27 28 END; this is probably better 1 CREATE OR REPLACE PROCEDURE primes(n integer) 2 IS 3 4 TYPE tab_type IS TABLE OF NUMBER 5 INDEX BY PLS_INTEGER; 6 7 stuff tab_type; 8 counter integer := 0; 9 counter2 integer; 10 11 BEGIN 12 FOR i in 2..n LOOP 13 IF prim(i) > 0 THEN 14 stuff(counter) := i; 15 counter := counter+1; 16 END IF; 17 END LOOP; 18 19 FOR i in stuff.FIRST..stuff.LAST LOOP 20 DBMS_OUTPUT.PUT_LINE('PRIMES: ' || stuff(i)); 21 END LOOP; 22 23 24 END; 25 / 26 set serveroutput on 27 call primes(100); Cursor and associative array Write a plsql procedure which takes the employees in alphabetical order and puts every second employee's name (1st, 3rd, 5th etc.) and salary into an associative array. The program should print out the last but one (the one before the last) values from the array. Going through them all 1 CREATE OR REPLACE PROCEDURE proc9 2 IS 3 4 CURSOR cur_emp IS 5 SELECT ename, sal 6 FROM emp 7 ORDER BY ename; 8 9 rec cur_emp%ROWTYPE; 10 11 TYPE tab_type IS TABLE OF PLS_INTEGER 12 INDEX BY varchar2(40); 13 14 stuff tab_type; 15 v_counter integer := 1; 16 v_index varchar2(40); 17 18 BEGIN 19 20 OPEN cur_emp; 21 22 LOOP 23 FETCH cur_emp INTO rec; 24 EXIT WHEN cur_emp%NOTFOUND; 25 IF mod(v_counter, 2) > 0 THEN 26 stuff(rec.ename) := rec.sal; 27 END IF; 28 v_counter := v_counter+1; 29 END LOOP; 30 31 v_index := stuff.FIRST; 32 33 WHILE (v_index is not null) LOOP 34 DBMS_OUTPUT.PUT_LINE('Ename : ' || v_index || ' sal: ' || TO_CHAR(stuff(v_index))); 35 v_index := stuff.next(v_index); 36 END LOOP; 37 38 39 CLOSE cur_emp; 40 41 END; 42 / 43 set serveroutput on 44 call proc9(); Actual Task 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 CREATE OR REPLACE PROCEDURE proc9 IS CURSOR cur_emp IS SELECT ename, sal FROM emp ORDER BY ename; rec cur_emp%ROWTYPE; TYPE tab_type IS TABLE OF PLS_INTEGER INDEX BY varchar2(40); stuff tab_type; v_counter integer := 1; v_index varchar2(40); BEGIN OPEN cur_emp; LOOP FETCH cur_emp INTO rec; EXIT WHEN cur_emp%NOTFOUND; IF mod(v_counter, 2) > 0 THEN stuff(rec.ename) := rec.sal; END IF; v_counter := v_counter+1; END LOOP; v_index := stuff.LAST; v_index := stuff.prior(v_index); DBMS_OUTPUT.PUT_LINE('Ename: ' || v_index || ' Sal: ' || stuff(v_index)); CLOSE cur_emp; END; / set serveroutput on call proc9(); Insert, Delete, Update Write a procedure which increases the salary of the employees who has salary category p (p is parameter). The increment should be the minimal salary of the employee's own department. After executing the update statement, the procedure should print out the average salary of all employees. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 CREATE OR REPLACE PROCEDURE upd_cat(p integer) IS CURSOR cur_sal IS select avg(sal) FROM emp; v_avgsal emp.sal%TYPE; BEGIN update emp e1 set sal = sal + (select min(sal) from emp e2 where e2.deptno = e1.deptno) where e1.sal between (select lowest_sal from sal_cat s1 where e1.sal between lowest_sal and highest_sal and category = p) and (select highest_sal from sal_cat where e1.sal between lowest_sal and highest_sal and category = p); OPEN cur_sal; FETCH cur_sal into v_avgsal; DBMS_OUTPUT.PUT_LINE(v_avgsal); END; / set serveroutput on call upd_cat(1); 1 create or replace PROCEDURE upd_cat2(p integer) 2 /* 3 Write a procedure which increases the salary of the employees who has salary category p (p is parameter). 4 The increment should be the minimal salary of the employee's own department. 5 After executing the update statement, the procedure should print out the average salary of all employees. 6 */ 7 IS 8 9 CURSOR cur_emp IS 10 SELECT * FROM emp, sal_cat 11 WHERE sal between lowest_sal and highest_sal 12 AND category = p 13 FOR UPDATE; 14 15 rec cur_emp%ROWTYPE; 16 avg_sal emp.sal%TYPE; 17 begin 18 19 OPEN cur_emp; 20 21 LOOP 22 FETCH cur_emp INTO rec; 23 24 EXIT WHEN cur_emp%NOTFOUND; 25 DBMS_Output.Put_Line('HELLO'); 26 27 UPDATE emp e1 SET sal = sal + 28 (SELECT min(sal) FROM emp 29 where rec.deptno = deptno) 30 WHERE e1.ename = rec.ename; 31 32 33 END LOOP; 34 CLOSE cur_emp; 35 36 37 select avg(sal) into avg_sal from emp; 38 DBMS_Output.Put_Line('Avg sal: ' || to_char(avg_sal)); 39 end; 40 / 41 42 set serveroutput on 43 call upd_cat2(1); 1 create or replace PROCEDURE upd_cat3(p integer) 2 /* 3 Write a procedure which increases the salary of the employees who has salary category p (p is parameter). 4 The increment should be the minimal salary of the employee's own department. 5 After executing the update statement, the procedure should print out the average salary of all employees. 6 */ 7 IS 8 9 v_avgsal emp.sal%TYPE; 10 11 BEGIN 12 13 UPDATE emp e1 SET sal = sal + 14 (select min(sal) from emp e3 where e1.deptno = e3.deptno) 15 where e1.ename IN (select ename from emp e2, sal_cat 16 where e2.sal between lowest_sal and highest_sal 17 AND category = p); 18 19 20 SELECT avg(sal) into v_avgsal from emp; 21 DBMS_OUTPUT.PUT_LINE(v_avgsal); 22 END; 23 / 24 set serveroutput on 25 call upd_cat3(1); Update with cursor Write a procedure which updates the salaries on a department (parameter: department number). The update should increase the salary with n*10000, where n is the number of vowels (A,E,I,O,U) in the name of the employee. (For ALLEN it is 2, for KING it is 1.) The procedure should print out the name and new salary of the modified employees. 1 CREATE OR REPLACE PROCEDURE curs_upd(dno INTEGER) 2 IS 3 4 Cursor Cur_Ename Is 5 Select Ename From Emp; 6 7 Rec Cur_Ename%Rowtype; 8 9 10 Cursor Cur_Enameandsal Is 11 Select Ename, Sal From Emp 12 Where Deptno = Dno; 13 14 Rec2 Cur_Enameandsal%Rowtype; 15 16 V_Numtimes Integer := 0; 17 18 Begin 19 20 Open Cur_Ename; 21 22 Loop 23 24 Fetch Cur_Ename Into Rec; 25 Exit When Cur_Ename%Notfound; 26 27 V_Numtimes := V_Numtimes + Num_Times(Rec.Ename,'A') + Num_Times(Rec.Ename,'E') 28 + Num_Times(Rec.Ename,'I') + Num_Times(Rec.Ename,'O') + Num_Times(Rec.Ename,'U'); 29 Dbms_Output.Put_Line('Number of vowels: ' || V_Numtimes); 30 31 Update Emp E1 Set Sal = Sal + 32 (V_Numtimes*100) 33 Where E1.Deptno = Dno 34 And Ename = Rec.Ename; 35 36 V_Numtimes := 0; 37 38 End Loop; 39 40 Open Cur_Enameandsal; 41 Loop 42 Fetch Cur_Enameandsal Into Rec2; 43 Exit When Cur_Enameandsal%Notfound; 44 Dbms_Output.Put_Line('Ename: ' || Rec2.Ename || ' New Sal: ' || Rec2.Sal); 45 End Loop; 46 47 Close Cur_Ename; 48 Close Cur_Enameandsal; 49 50 End; 51 / 52 53 Set Serveroutput On 54 Call Curs_Upd(10); Exceptions (exception) Write a function which gets a date parameter in one of the following formats: 'yyyy.mm.dd' or 'dd.mm.yyyy'. The function should return the name of the day, e.g. 'Tuesday'. If the parameter doesn't match any of the formats, the function should return 'wrong format'. Hint: try to convert the string to date and handle the exception if the conversion fails. 1 CREATE OR REPLACE FUNCTION day_name(d varchar2) 2 RETURN varchar2 3 IS 4 --v_date DATE; 5 v_string varchar2(40); 6 7 BEGIN 8 9 CASE 10 WHEN REGEXP_LIKE (d, '\d{4}.\d{2}.\d{2}') THEN 11 v_string := to_char(to_date(d, 'YYYY-MM-DD'), 'Day'); 12 WHEN REGEXP_LIKE (d, '\d{2}.\d{2}.\d{4}') THEN 13 v_string := to_char(to_date(d,'DD-MM-YYYY'), 'Day'); 14 ELSE 15 v_string := to_char(to_date(d, 'YYYY-MM-DD')); 16 END CASE; 17 18 Dbms_Output.Put_Line('Date is : ' || v_string); 19 20 RETURN v_string; 21 22 23 EXCEPTION 24 WHEN OTHERS THEN 25 DBMS_OUTPUT.PUT_LINE('Code is: '|| SQLCODE); 26 Dbms_Output.Put_Line('Message is: ' || SQLERRM); 27 28 RETURN v_string; 29 30 31 END; 32 / 33 set Serveroutput On 34 SELECT day_name('2017.05.01') FROM dual; 35 set Serveroutput On 36 SELECT day_name('02.05.2017') FROM dual; 37 set Serveroutput On 38 SELECT day_name('abc') FROM dual; Another Way I guess 1 CREATE OR REPLACE FUNCTION day_name2(d varchar2) 2 RETURN varchar2 3 IS 4 v_date DATE; 5 v_string varchar2(40); 6 e_notvalid EXCEPTION; 7 e_wrongFormat EXCEPTION; 8 PRAGMA EXCEPTION_INIT(e_notvalid, -1830); 9 PRAGMA EXCEPTION_INIT(e_wrongFormat, -1841); 10 11 BEGIN 12 v_string := to_char(to_date(d, 'YYYY.MM.DD'), 'Day'); 13 RETURN v_string; 14 15 EXCEPTION 16 WHEN e_notvalid THEN 17 v_string := to_char(to_date(d, 'DD.MM.YYYY'), 'Day'); 18 RETURN v_string; 19 20 WHEN e_wrongFormat THEN 21 DBMS_OUTPUT.PUT_LINE('Code is: '|| SQLCODE); 22 Dbms_Output.Put_Line('Message is: ' || SQLERRM); 23 RETURN v_string; 24 25 WHEN OTHERS THEN 26 DBMS_OUTPUT.PUT_LINE('Code is: '|| SQLCODE); 27 Dbms_Output.Put_Line('Message is: ' || SQLERRM); 28 RETURN v_string; 29 30 31 END; 32 / 33 set Serveroutput On 34 SELECT day_name2('2017.05.01') FROM dual; 35 set Serveroutput On 36 SELECT day_name2('02.05.2017') FROM dual; 37 set Serveroutput On 38 SELECT day_name2('abc') FROM dual; exception, SQLCODE Write a procedure which gets a number parameter and prints out the reciprocal, the sqare root and the factorial of the parameter in different lines. If any of these outputs is not defined or causes an overflow, the procedure should print out 'not defined' or the error code (SQLCODE) for this part. (The factorial is defined only for nonnegative integers.) 1 CREATE OR REPLACE PROCEDURE numbers(n number) 2 IS 3 v_inverse number(10,3); 4 too_low EXCEPTION; 5 PRAGMA EXCEPTION_INIT(too_low, -3001); 6 7 BEGIN 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 Dbms_Output.Put_Line('Factorial is : ' || factor(n)); --Our own v_inverse := 1/n; Dbms_Output.Put_Line('Inverse is : ' || v_inverse); Dbms_Output.Put_Line('Square Root is : ' || sqrt(n)); EXCEPTION WHEN ZERO_DIVIDE THEN DBMS_OUTPUT.PUT_LINE('Code is: '|| SQLCODE); Dbms_Output.Put_Line('Not defined'); WHEN too_low THEN DBMS_OUTPUT.PUT_LINE('Code is: '|| SQLCODE); Dbms_Output.Put_Line('Too low'); WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('Code is: '|| SQLCODE); Dbms_Output.Put_Line('Some other exception'); END; / set serveroutput on call numbers(0); -- -01476 divide by 0 set serveroutput on call numbers(-2); set serveroutput on call numbers(40); -- -06512 too large (exception) Write a function which returns the sum of the numbers in its string parameter. The numbers are separated with a '+'. If any expression between the '+' characters is not a number, the function should consider this expression as 0. CREATE OR REPLACE FUNCTION sum_of2(p_char VARCHAR2) RETURN number IS Tesztelés: SELECT sum_of2('1+21 + bubu + + 2 ++') FROM dual; Hint: try to convert the expressions to number, and handle the exception 1 CREATE OR REPLACE FUNCTION sum_of2(p_char VARCHAR2) RETURN number 2 IS 3 4 v_substring varchar2(50); 5 v_stringcopy varchar2(50) := p_char; --Maybe stupid I donno 6 v_plusposition integer; 7 v_stringposition integer := 1; 8 v_counter integer := 0; 9 10 BEGIN 11 12 WHILE (length(v_stringcopy) > 0) LOOP 13 v_plusposition := INSTR(v_stringcopy, '+'); 14 v_substring := substr(v_stringcopy, v_stringposition, v_plusposition-1); 15 Dbms_Output.Put_Line('In between :' || v_substring); 16 v_stringcopy := substr(v_stringcopy, v_plusposition+1); 17 Dbms_Output.Put_Line('String Copy is Now: ' || v_stringcopy); 18 Dbms_Output.Put_Line('Counter before : ' || v_counter); 19 begin 20 IF v_substring is not null THEN 21 v_counter := v_counter + to_number(v_substring); 22 Dbms_Output.Put_Line('Counter after : ' || v_counter); 23 END IF; 24 exception 25 WHEN OTHERS THEN 26 DBMS_OUTPUT.PUT_LINE('Code is: '|| SQLCODE); 27 end; 28 29 END LOOP; 30 return v_counter; 31 32 33 END; 34 / 35 36 set Serveroutput On 37 SELECT sum_of2('1+21 + bubu + + 2 ++') FROM dual; Exam 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 create or replace FUNCTION sum_of (p_char VARCHAR2) /* Write a function which returns the sum of the numbers in its string parameter. The numbers are separated with a '+'. */ RETURN number IS v_sum integer := 0; v_stringcopy varchar(50) := p_char; v_plusposition integer := instr(p_char, '+'); v_substring varchar(50); BEGIN WHILE length(v_stringcopy) > 0 LOOP IF v_plusposition = 0 THEN EXIT; END IF; v_substring := substr(v_stringcopy, 1, v_plusposition-1); Dbms_Output.Put_Line('substring: ' || v_substring ); v_sum := v_sum + to_number(v_substring); Dbms_Output.Put_Line('sum: ' || v_sum ); v_stringcopy := substr(v_stringcopy, v_plusposition+1); Dbms_Output.Put_Line('stringcopy : ' || v_stringcopy ); v_plusposition := instr(v_stringcopy, '+'); END LOOP; RETURN v_sum; 29 30 END; 2 1 create or replace PROCEDURE primes(n integer) 2 --ASSOCIATIVE ARRAY EXAMPLE 3 IS 4 5 TYPE tab_type IS TABLE OF NUMBER --Define type of associative array 6 INDEX BY PLS_INTEGER; --How its indexed 7 8 stuff tab_type; --Declare an associative array of the type defined above 9 counter integer := 0; 10 summedprimes integer := 0; 11 counter2 integer := 2; 12 13 BEGIN 14 WHILE stuff.COUNT < n LOOP 15 IF prim(counter2) > 0 THEN 16 stuff(counter) := counter2; 17 counter := counter+1; 18 END IF; 19 counter2 := counter2+1; 20 END LOOP; 21 22 DBMS_OUTPUT.PUT_LINE('The last Prime is: ' || stuff(stuff.LAST)); 23 24 25 FOR i in stuff.FIRST..stuff.LAST LOOP 26 summedprimes := summedprimes + stuff(i); 27 END LOOP; 28 DBMS_OUTPUT.PUT_LINE('Sum of Primes ' || summedprimes); 29 30 END; 3 1 3. 2 create or replace PROCEDURE upd_cat7(p integer) 3 /* 4 Write a procedure which increases the salary of the employees who has salary category p (p is parameter). 5 The increment should be the commission of the employee, or if it is NULL, then the increment is 100. 6 After executing the update statement, the procedure should print out the average salary of all employees. 7 At the very end (after printing out the average) the procedure should give a ROLLBACK statement 8 to save the original content of the table, in order to be able to run it several times. 9 */ 10 IS 11 12 v_avgsal emp.sal%TYPE; 13 14 BEGIN 15 16 17 18 19 20 21 22 23 24 25 26 27 UPDATE emp e1 SET sal = sal + nvl((select comm from emp e3 where e1.ename = e3.ename),100) where e1.ename IN (select ename from emp e2, sal_cat where e2.sal between lowest_sal and highest_sal AND category = p); SELECT avg(sal) into v_avgsal from emp; DBMS_OUTPUT.PUT_LINE(v_avgsal); rollback; END; 4 1 create or replace PROCEDURE curs_upd(dno INTEGER) 2 IS 3 /*Write a procedure which updates the salaries on a department (parameter: department number). 4 The update should increase the salary with n*10000, where n is the number of vowels (A,E,I,O,U) 5 in the name of the employee. (For ALLEN it is 2, for KING it is 1.) 6 The procedure should print out the name and new salary of the modified employees.*/ 7 8 CURSOR cur_ename IS 9 select ename from emp; 10 11 rec cur_ename%ROWTYPE; 12 13 14 CURSOR cur_enameAndSal IS 15 select ename, sal from emp 16 where deptno = dno; 17 18 rec2 cur_enameAndSal%ROWTYPE; 19 20 v_numTimes integer := 0; 21 22 BEGIN 23 24 OPEN cur_ename; 25 26 LOOP 27 28 FETCH cur_ename INTO rec; 29 EXIT WHEN cur_ename%NOTFOUND; 30 31 v_numTimes := v_numTimes + num_times(rec.ename,'A') + num_times(rec.ename,'E') + num_times(rec.ename,'I') + num_times(rec.ename,'O') + num_times(rec.ename,'U'); 32 DBMS_OUTPUT.PUT_LINE('Number of vowels: ' || v_numTimes); 33 34 update emp e1 set sal = sal + 35 (v_numTimes*10000) 36 where e1.deptno = dno 37 and ename = rec.ename; 38 39 v_numTimes := 0; 40 41 END LOOP; 42 43 OPEN cur_enameAndSal; 44 LOOP 45 FETCH cur_enameAndSal INTO rec2; 46 EXIT WHEN cur_enameAndSal%NOTFOUND; 47 DBMS_OUTPUT.PUT_LINE('Ename: ' || rec2.ename || ' New Sal: ' || rec2.sal); 48 END LOOP; 49 50 close cur_ename; 51 close cur_enameAndSal; 52 53 END; 54 55 -------------------------------------------------------56 4.1 57 58 create or replace FUNCTION num_times(p1 varchar2, p2 varchar2) 59 RETURN integer 60 IS 61 v_position integer; 62 v_position2 integer; 63 v_stringy varchar2(40) := p1; 64 v_count integer := 0; 65 BEGIN 66 67 FOR i IN 1..length(p1) LOOP 68 v_position := instr(v_stringy, p2) + length(p2); 69 v_position2 := instr(v_stringy,p2); 70 IF v_position2 > 0 THEN 71 v_count := v_count+1; 72 END IF; 73 v_stringy := substr(v_stringy, v_position); 74 END LOOP; 75 76 return v_count; 77 END; 5 1 create or replace FUNCTION primefactor(p1 integer) RETURN varchar2 2 IS 3 4 v_string varchar2(50); 5 v_number integer := p1; 6 BEGIN 7 8 FOR i IN 2..v_number LOOP 9 WHILE mod(v_number, i) = 0 LOOP 10 v_string := v_string || to_char(i) || '*'; 11 v_number := v_number / i; 12 END LOOP; 13 END LOOP; 14 v_string := substr(v_string, 0, length(v_string)-1); 15 return v_string; 16 END;