Uploaded by Edimarf Satumbo

PL-SQL

advertisement
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;
Download