Oracle data modeler: How Create prodcedure and function - oracle

How create procedure e.g.:
Create PROCEDURE il_klub as (
select
sum(krk.kluby_id),
r.nazwa
FROM
rozgrywki_klubowe r,
kluby_roz_klub krk
WHERE
r.id = krk.rozgrywki_klubowe_id
GROUP by r.nazwa
)
and function e.g.:
DECLARE #mistrz TABLE (nazwa varchar, rozgrywki varchar)
INSER INTO #mistrz (nazwa, rozgrywki)
select
k.nazwa, r.nazwa
from
kluby k,
rozgrywki_klubowe r,
kluby_roz_klub krk,
historia_roz_klub hrk,
where
k.id = krk.kluby_id and k.id = hrk.kluby_id and r.id = krk.rozgrywki_klubowe_id
and r.id = hrk.rozgrywki_klubowe_id
and hrk.miejsce =1 and r.system like 'ligowy'
Select * from #mistrz
In Oracle SQL Data Modeler

The syntax for a procedure declaration is
CREATE OR REPLACE PROCEDURE IL_KLUB AS
vSUM_KLUBY KLUBY_ROZ_KLUB%TYPE;
vNAZWA ROZGRYWKI_KNUBOWE.NAZWA%TYPE;
BEGIN
select sum(krk.kluby_id),
r.nazwa
INTO vSUM_KLUBY,
vNAZWA
FROM rozgrywki_klubowe r,
kluby_roz_klub krk
WHERE r.id = krk.rozgrywki_klubowe_id
GROUP by r.nazwa;
END IL_KLUB;
This procedure is, obviously, not particularly useful as it doesn't do anything with the results of the SELECT, and that will probably draw a compilation warning. But that's how you declare it.
A function is defined in similar fashion, but you also need to define a return type, and then return a value:
CREATE OR REPLACE FUNCTION IL_KLUB_NAZWA
RETURN ROZGRYWKI_KNUBOWE.NAZWA%TYPE
AS
vSUM_KLUBY KLUBY_ROZ_KLUB%TYPE;
vNAZWA ROZGRYWKI_KNUBOWE.NAZWA%TYPE;
BEGIN
select sum(krk.kluby_id),
r.nazwa
INTO vSUM_KLUBY,
vNAZWA
FROM rozgrywki_klubowe r,
kluby_roz_klub krk
WHERE r.id = krk.rozgrywki_klubowe_id
GROUP by r.nazwa;
RETURN vNAZWA;
END IL_KLUB_NAZWA;
Oracle PL/SQL Language Reference here
Oracle SQL Language Reference here
Best of luck.

Related

How to define a parameter that will be used as an IN argument inside a function?

I want to make a function that receives two parameters. The first one represents the salaries from a group of employees, and second one, the codes from a group of departments. Both, P_IN_SALARIES and P_IN_DEPARTMENTS_CODES parameters, will be used as
arguments in an IN function of a query, just as demonstrated in the code below:
CREATE OR REPLACE FUNCTION public.get_employees_id(P_IN_SALARIES WHICH_TYPE_COMES_HERE, P_IN_DEPARTMENTS_CODES WHICH_TYPE_COMES_HERE)
RETURNS text
LANGUAGE plpgsql
AS $function$
declare
v_employees_ids text;
begin
select STRING_AGG(employee.id || '', ',') into v_employees_ids
from employee
inner join departament on department.id = employee.departament_id
where employee.salary in (P_IN_SALARIES)
and department.code in (P_IN_DEPARTMENTS_CODES);
RETURN v_employees_ids;
END;
$function$
What is the type of a IN parameter in a SQL statement?
Is there a generic one that I might use in order to allow a kind of portability on an occasional database exchange (e.g. to Oracle)?
How to call this function in a hibernate query?
In Oracle, you can use a collection data type:
CREATE TABLE number_list IS TABLE OF NUMBER;
Then you can use the MEMBER OF operator rather than IN:
CREATE FUNCTION public.get_employees_id(
P_IN_SALARIES IN number_list,
P_IN_DEPARTMENTS_CODES IN number_list
) RETURNS VARCHAR2
IS
v_employees_ids VARCHAR2(4000);
BEGIN
SELECT LISTAGG( id, ',' ) WITHIN GROUP ( ORDER BY id )
INTO v_employees_ids
FROM employee e
inner join departament d
on ( d.id = e.departament_id )
WHERE e.salary MEMBER OF P_IN_SALARIES
AND d.department.code MEMBER OF P_IN_DEPARTMENTS_CODES;
RETURN v_employees_ids;
END;
/

PL/SQL error "not enough values" during "select into"

I'm working on creating a pl/sql function that finds the highest average of students from a list of classes. I have the average computation part working correctly; however, I need to return the results as a table of records and I'm running into the error while attempting to store the results into the record.
My record declaration is as follows
create or replace TYPE studentRec as object (
term varchar2(10),
lineNum number(4),
coTitle varchar2(50),
stuId varchar2(5),
average number);
The error comes when I'm trying to fill the record using a select into statement.
create or replace function highest_avg(stu_id scores.sid%type,
line_no scores.lineno%type)
return stuRecTab
as
stuRec stuRecTab;
average number;
studentRec_t studentRec;
begin
stuRec := stuRecTab();
select avg(points)
into average
from scores, courses
where scores.sid = stu_id
and scores.lineno = line_no
and scores.term = courses.term
and scores.lineno = courses.lineno;
SELECT DISTINCT c.term, c.lineno, cc.ctitle, s.sid, average
INTO studentRec_t
from courses c, class_catalog cc, scores s
where s.sid = stu_id
and s.lineno = line_no
and s.term = c.term
and s.lineno = c.lineno
and c.cno = cc.cno;
stuRec := studentRec_t;
return(stuRec);
end;
I've run it as just a query and I'm getting back what I expect so I'm not sure why this error is popping up. Any help would be greatly appreciated as this is my first time working with pl/sql.
First, you can't SELECT INTO the fields of an object instance variable - you have to create an object instance in your select, then SELECT that INTO your object instance variable. You can't simply assign an instance variable to a collection - you need to put it at an appropriate index. So what you end up with is something like:
create or replace function highest_avg(stu_id scores.sid%type,
line_no scores.lineno%type)
return stuRecTab
as
stuRec stuRecTab;
average number;
studentRec_t studentRec;
begin
stuRec := stuRecTab();
select avg(points)
into average
from scores s
inner join courses c
on c.term = s.term and
c.lineno = s.lineno
where s.sid = stu_id and
s.lineno = line_no;
SELECT studentRec(term, lineno, ctitle, sid, average)
INTO studentRec_t
FROM (SELECT DISTINCT c.term, c.lineno, cc.ctitle, s.sid, average
from scores s
INNER JOIN courses c
ON s.term = c.term and
s.lineno = c.lineno
INNER JOIN class_catalog cc
ON cc.cno = c.cno
where s.sid = stu_id and
s.lineno = line_no);
stuRec(1) := studentRec_t;
return(stuRec);
end;
As no test data was provided I haven't tested this - but at least it compiles at dbfiddle.

Oracle function perform better than inline query

I have one long query which have a lot of let join with subqueries. It 's have some performance issue. I have just put subqueries inside new function and the function execute that subqueries and store the output in a collection (user defined table which contain user defined object). when I execute outer query with this function it's perform better than subqueries but we don't found the answer why it's happend.
Example : Existing Query
select *
from a
left join (select * from b left join c on b.something =c.something where b.something=`something`) d on a.something = d.something
Update the query
create object user_obj as ( column_name varchar, column_name varchar);
create or replace TYPE table_name AS TABLE OF user_obj;
create function test (something) as
report table_name := table_name();
Begin
for i in (select * from b left join c on b.something =c.something where
b.something='something')loop
report.EXTEND;
report(report.count) := (user_obj(i.firstcolumnvalue,
i.secondColumnValue))
end loop;
return report;
End
calling function by outer query
select * from a left join (select * from table(test(input_data))) d on a.something = d.something
When I executing through function it's give me better performance as compare to inline query
I want a reason why performance is better in function

Write an Oracle procedure

I must create an oracle procedure to display a list of persons (parlimentaries) with an index for tuples.
For now, I wrote this piece of code (I haven't implemented the index)
create or replace procedure parlamentarieslist as
begin
select
ssn,
name,
surname,
from
parlimentaries p,
mandate m
where
p.ssn = m.parlamentaries AND m.legislature= (select
max(legislature) "m"
from mandate);
end parlamentarieslist;
However, oracle give me these errors
Error(5,3): PL/SQL: SQL Statement ignored
Error(12,3): PL/SQL: ORA-00936: missing expression
Why?
As I mentioned before in the comment part, the problem is due to
the missing INTO clause
existing typo(comma) after surname column in the uppermost select list.
Mostly, Procedures are used to return one column or single row and in results of SELECT statements may be returned to the output parameters by INTO clause. But, If you want to return list of persons (multi-rows), the following style may be more suitable :
SQL> set serveroutput on;
SQL> create or replace procedure parlamentarieslist as
begin
for c in
(
select p.ssn, p.name, p.surname,
max(m.legislature) over (partition by p.ssn ) m
from parlimentaries p inner join mandate m
on ( p.ssn = m.parlamentaries )
order by m.legislature desc
)
loop
dbms_output.put_line(' SSN : '||c.ssn||' Name : '||c.name||' Surname : '||c.surname);
end loop;
end parlamentarieslist;
/
SQL> exec parlamentarieslist;
Where Use a SQL of explict ANSI JOIN style, instead of old-fashioned comma seperated JOIN style.

PL/SQL: Loop through and alter REFCURSOR rows before returning to calling procedure

I have a refcursor in a function, declared like this:
my_cursor type_refcur_my
And populated as such:
OPEN my_cursor FOR
SELECT DISTINCT A.vegetable, A.animal, A.mineral, A.ID,
(SELECT DISTINCT SUBSTR(bcptr.bcptr_desc_l1,INSTR(bcptr.bcptr_desc_l1,')',-1)-3,3)
FROM doe D, ray R, me M
WHERE ...) ID
FROM artifacts A
ORDER BY vegetable, mineral;
RETURN my_cursor;
I need to perform an operation that involves another SELECT on all the rows in the recursor and use some logic to alter 2 of the column values before returning it. Something kind of like:
IF my_cursor.vegetable = (SELECT B.ID from vegetables B
WHERE my_cursor.vegetable = B.vegetable_description)
THEN
my_cursor.A.ID := B.ID
END IF;
My thought was to put this code after opening the cursor and before returning it. But this produces compile errors, and I cannot find an appropriate example online.I appreciate your help.

Resources