calculate gpa oracle pl sql - sql

I am a noobie in pl/sql. I am trying t calculate gpa using pl sql. i have created a table with grades with values in it.
SSN CNO GRADE
--------------- -------- ----------
55555 cs101 1
55555 math101 4
55555 bio101 1
55555 cgdd101 3
55555 swe203 3
55555 eng101 3
11111 bio101 4
11111 cgdd101 4
55555 cs101 1
55555 math101 4
55555 bio101 1
I am trying to calculate gpa with the following pl sql function but I get the following error.
55555 eng101 3
36 rows selected.
SQL> create or replace function get_count
2 return is
3 declare
4 v_count number;
5 begin
6 select count(*) into v_count from grade;
7 return grade;
8
9 end;
10 /
Warning: Function created with compilation errors.
SQL> show errors
Errors for FUNCTION GET_COUNT:
LINE/COL ERROR
-------- -----------------------------------------------------------------
2/8 PLS-00103: Encountered the symbol "IS" when expecting one of the
following:
<an identifier> <a double-quoted delimited-identifier> self
long double ref char time timestamp interval date binary
national character nchar

Your function is missing a return data type, e.g.:
create or replace function get_count
return NUMBER is
v_count number;
...
Also, you don't need the declare.

Try This
CREATE OR REPLACE FUNCTION GET_COUNT
RETURN NUMBER
IS
V_COUNT NUMBER;
BEGIN
SELECT COUNT (*)
INTO V_COUNT
FROM GRADE;
RETURN V_COUNT;
END;

Related

Select statement inside a Procedure gives me a error, why?

I'm new to pl/SQL, and I'm trying to create a procedure that displays the values from the table 'BUS'. Please help me out here.
I'm using SQL*Plus as a command-line interface tool for Oracle Database 10g Enterprise Edition Release 10.2.0.1.0.
SQL> create or replace procedure get_bus_table
2 in
3 begin
4 select * from bus;
5 end;
6 /
Warning: Procedure created with compilation errors.
There are various errors (there's no in but is or as; PL/SQL requires an INTO clause, but that probably wouldn't help here; you didn't say how would you want to display data contained in the table).
Sample data:
SQL> select * from bus;
ROUTENO SOURCE DESTINATION
---------- ------- -----------
1 chennai bangalore
101 PUNE CHENNAI
102 PUNE BANGALORE
103 CHENNAI PUNE
Here's one option: a procedure that loops through the table and uses dbms_output.put_line:
SQL> create or replace procedure get_bus_table is
2 begin
3 for cur_r in (select routeno, source, destination
4 from bus)
5 loop
6 dbms_output.put_line(cur_r.routeno ||' - '|| cur_r.source ||' - '||
7 cur_r.destination);
8 end loop;
9 end;
10 /
Procedure created.
Testing:
SQL> set serveroutput on
SQL> begin
2 get_bus_table;
3 end;
4 /
1 - chennai - bangalore
101 - PUNE - CHENNAI
102 - PUNE - BANGALORE
103 - CHENNAI - PUNE
PL/SQL procedure successfully completed.
SQL>
Or, maybe you wanted to use a function (instead of a procedure):
SQL> create or replace type t_row as object
2 (routeno number,
3 source varchar2(20),
4 destination varchar2(20));
5 /
Type created.
SQL> create or replace type t_tab as table of t_row;
2 /
Type created.
SQL> create or replace function f_get_bus_table
2 return t_tab
3 is
4 l_tab t_tab;
5 begin
6 select t_row(routeno, source, destination)
7 bulk collect into l_tab
8 from bus;
9 return l_tab;
10 end;
11 /
Function created.
Let's try it:
SQL> select * from table(f_get_bus_table);
ROUTENO SOURCE DESTINATION
---------- -------------------- --------------------
1 chennai bangalore
101 PUNE CHENNAI
102 PUNE BANGALORE
103 CHENNAI PUNE
SQL>
There's also a ref cursor procedure in another answer to your question; I suggest you check it.
Use:
select * from bus;
and do not use a procedure.
If you want to use a procedure then you will need to SELECT into something; that could be variable(s), collection(s) or a cursor. For example:
CREATE PROCEDURE get_bus_table(
o_cur OUT SYS_REFCURSOR
)
IS
BEGIN
OPEN o_cur FOR
select * from bus;
END get_bus_table;
/
Then, when you call the procedure, you can process the returned cursor.
db<>fiddle here
A select clause in procedure needs INTO with it and a variable to store the data in. You can use record for Bus table or you can use cursor. Both should be fine.

How to select a table using a string in Oracle?

First of all, I know the question is vague, so feel free to edit it if you can describe it better.
There are some sets of table like TEST_201812, TEST_201901, etc. . I have another table that stores these values:
TEST_DATE:
ID DATE
1 201810
2 201811
3 201812
4 201901
Now what I want is to select the tables mentioned above (e.g.TEST_201812) by using TEST_DATE. I know it's wrong, but something like this:
select * from TEST_(select DATE from TEST_DATE where ID = 1)
Does anyone know how to achieve this?
Seriously, such a data model is a disaster. If you want to keep separate months separately, use one - partitioned - table.
Anyway, here's one option of how to do that:
Sample tables and a function that returns refcursor:
SQL> create table test_201812 as select * From dept;
Table created.
SQL> create table test_date (id number, datum number);
Table created.
SQL> insert into test_date values (1, 201812);
1 row created.
SQL> create or replace function f_test (par_id in test_date.id%type)
2 return sys_refcursor
3 is
4 l_datum test_date.datum%type;
5 l_str varchar2(200);
6 l_rc sys_refcursor;
7 begin
8 select datum
9 into l_datum
10 from test_date
11 where id = par_id;
12
13 l_str := 'select * from test_' || l_datum;
14 open l_rc for l_str;
15 return l_rc;
16 end;
17 /
Function created.
Testing:
SQL> select f_test(1) from dual;
F_TEST(1)
--------------------
CURSOR STATEMENT : 1
CURSOR STATEMENT : 1
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
SQL>

My procedures update statement is leaving a null value in my table

I am trying to write a function that retrieves the number of hours that a user defined consultant has been assigned to a user defined project and the value should be returned to the plsql anonymous block calling the function. My procedure should update the number of hours that the consultant has been assigned to the project.
UPDATE: ok so I edited my code and finally got the function to return the correct value. Now all I need is to call my procedure to actually update the tables. The IF statement in my anonymous block doesnt seem to recognize the newtotal_hours. Any ideas???
NEW UPDATE ok so I got everything compiling and returning as it should be however the only problem I have left is that my procedure's update statement is causing a null value in the table where the updated newtotal_hours should replace it how can I fix this???
Here is my table:
project_consultant
(p_id number(6),
c_id number(6),
total_hours number(6)
);
and here is my WORKING UPDATED FUNCTION:
create or replace function return_num_hours (pid number, cid number)
return number is
totalhrs project_consultant.total_hours%type;
cursor c1 is select total_hours from project_consultant where p_id=pid and c_id=cid;
begin
open c1;
fetch c1 into totalhrs;
close c1;
return totalhrs;
end;
/
and finally heres my procedure:
create or replace procedure update_hours (proj_id number, consult_id number) is
change_in_hours number(6);
project_id project_consultant.p_id%type;
consultant_id project_consultant.c_id%type;
totalhours project_consultant.total_hours%type;
cursor c2 is select p_id, c_id, total_hours from project_consultant where p_id=proj_id and
c_id=consult_id;
begin
open c2;
fetch c2 into project_id, consultant_id, totalhours;
totalhours := totalhours + change_in_hours;
update project_consultant set total_hours = totalhours where p_id = proj_id and c_id = consult_id;
--commit;
close c2;
end;
/
my user-defined anonymous block to call the function and procedure..
declare
totalnumhours number(6);
change_in_hours number(6);
newtotal_hours number(6);
project_id number(6);
consultant_id number(6);
begin
consultant_id := &consult_id;
project_id := &proj_id;
change_in_hours := &change_in_hours;
totalnumhours := return_num_hours(project_id, consultant_id);
dbms_output.put_line(totalnumhours);
newtotal_hours := totalnumhours + change_in_hours;
dbms_output.put_line(newtotal_hours);
if newtotal_hours > 0 then
update_hours(project_id, consultant_id);
dbms_output.put_line('Consultant ' ||consultant_id||' Project '||project_id||':'||' changed planned hours from '||totalnumhours||'
to '||newtotal_hours);
else
dbms_output.put_line('Cannot update number of hours to a negative total');
end if;
commit;
exception
when no_data_found then
dbms_output.put_line('No such consultant or project');
end;
/
script output for consultant_id:101 project_id:1
SQL> select * from project_consultant
P_ID C_ID TOTAL_HOURS
---------- ---------- -----------
1 101
1 104 245
1 103 50
1 105 45
2 105 25
2 100 0
3 103 125
3 104 50
4 105 25
4 104 125
4 102 30
P_ID C_ID TOTAL_HOURS
---------- ---------- -----------
5 105 15
5 103 15
6 103 5
6 104 10
7 102 125
7 100 100
17 rows selected.
In your function you return third input parameter totalhours as a result return(totalhours);. Is it ok? I guess that you want to return value of totalhrs

How to change PL/SQL function call when function is no longer pipelined?

I have PL/SQL function looking like:
FUNCTION get_agent_statistics ( id NUMBER
RETURN agent_stats_t
PIPELINED;
And I select from it (iBatis code):
SELECT * FROM table(pkg.get_agent_statistics(#id#))
How should I change this select if I'll remove PIPELINED statement from function?
If you'll get working compiled procedure without PIPELINED statement, you don't need to change your SELECT. See this - http://www.oracle-base.com/articles/misc/pipelined-table-functions.php
When you remove PIPELINED clause from the function declaration, function ceases to be a PIPELINED table function and as a result you will have to modify the body of the function to convert it to a TABLE function, if you still want to use it the from clause of the query, or a simple function, which you wont be able to use in the from clause of a query.
Addendum
Could I select something from non-pipelined function?
Yes, if you have a TABLE function, otherwise no. Here is a couple of examples:
-- prerequisites
SQL> create or replace type T_rows as object(
2 e_name varchar2(21),
3 e_lname varchar2(21)
4 )
5 /
Type created
SQL> create or replace type T_tab is table of t_rows
2 /
Type created
-- PIPELINED TABLE function
SQL> create or replace function GetEnames
2 return T_Tab
3 pipelined
4 is
5 l_etab t_tab := t_tab();
6 begin
7 for i in (select first_name
8 , last_name
9 from employees)
10 loop
11 pipe row(t_rows(i.first_name, i.last_name));
12 --l_etab.extend;
13 --l_etab(l_etab.last) := t_rows(i.first_name, i.last_name);
14 end loop;
15 return ;--l_etab;
16 end;
17 /
Function created
SQL> select *
2 from table(getenames)
3 where rownum <= 5;
E_NAME E_LNAME
--------------------- ---------------------
Steven King
Neena Kochhar
Lex De Haan
Alexander Hunold
Bruce Ernst
-- non-pipelined table function
SQL> create or replace function GetEnames
2 return T_Tab
3
4 is
5 l_etab t_tab := t_tab();
6 begin
7 for i in (select first_name
8 , last_name
9 from employees)
10 loop
11 --pipe row(t_rows(i.first_name, i.last_name));
12 l_etab.extend;
13 l_etab(l_etab.last) := t_rows(i.first_name, i.last_name);
14 end loop;
15 return l_etab;
16 end;
17 /
Function created
SQL> select *
2 from table(getenames)
3 where rownum <= 5;
E_NAME E_LNAME
--------------------- ---------------------
Steven King
Neena Kochhar
Lex De Haan
Alexander Hunold
Bruce Ernst
SQL>

How to call a function in a package

I'm doing the following but it doesnt work
select package_name.function_name(param,param) from dual
I'm calling a function that returns a cursor so im guessing "from dual" is the problem
is there another way of doing it?
I presume you mean a Ref Cursor. This is a PL/SQL construct which acts as a pointer to a set of records returned by a query. This means it has to be interpreted by the client which runs the query. For instance, we can map a Ref Cursor to a JDBC or ODBC ResultSet.
There is certainly nothing wrong with your basic statement. Here is a function similar to your own:
SQL> desc get_emps
FUNCTION get_emps RETURNS REF CURSOR
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
P_DNO NUMBER(2) IN
P_SORT_COL VARCHAR2 IN DEFAULT
P_ASC_DESC VARCHAR2 IN DEFAULT
SQL>
I can easily call this in a wider PL/SQL block:
SQL> declare
2 rc sys_refcursor;
3 begin
4 rc := get_emps(50);
5 end;
6 /
PL/SQL procedure successfully completed.
SQL>
However, SQL*PLus can handle CURSOR constructs natively:
SQL> select get_emps(50) from dual
2 /
GET_EMPS(50)
--------------------
CURSOR STATEMENT : 1
CURSOR STATEMENT : 1
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- --------- ---------- ---------- ----------
8060 VERREYNNE PLUMBER 8061 08-APR-08 4000 50
8061 FEUERSTEIN PLUMBER 7839 27-FEB-10 4500 50
8085 TRICHLER PLUMBER 8061 08-APR-10 3500 50
8100 PODER PLUMBER 8061 3750 50
SQL>
This statement also runs in SQL Developer, although the result set is laid out in an ugly fashion.
So, if you are having problems with your function, the questions are:
What client environment are you using?
In what precise fashion does it "not work"? Please describe the observed behaviour, including any error messages?
Also give us environment details such as the version of the database, the OS, etc.
Having read your other question on this topic I thought the problem might be due to the use of a User-Defined Ref Cursor (rather than the built-in). However, that doesn't make any difference. This packaged function:
SQL> create or replace package emp_rc_utils as
2
3 type emp_rc is ref cursor return emp%rowtype;
4
5 function get_emps
6 ( p_dno in emp.deptno%type
7 )
8 return emp_rc;
9 end;
10 /
Package created.
SQL> create or replace package body emp_rc_utils as
2
3 function get_emps
4 ( p_dno in emp.deptno%type
5 )
6 return emp_rc
7 is
8 return_value emp_rc_utils.emp_rc;
9 begin
10
11 open return_value for select * from emp where deptno = p_dno;
12
13 return return_value;
14 end get_emps;
15
16 end emp_rc_utils;
17 /
Package body created.
SQL>
Still works...
SQL> declare
2 rc sys_refcursor;
3 begin
4 rc := emp_rc_utils.get_emps(50);
5 end;
6 /
PL/SQL procedure successfully completed.
SQL> select emp_rc_utils.get_emps(50) from dual
2 /
EMP_RC_UTILS.GET_EMP
--------------------
CURSOR STATEMENT : 1
CURSOR STATEMENT : 1
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- --------- ---------- ---------- ----------
8085 TRICHLER PLUMBER 8061 08-APR-10 3500 50
8060 VERREYNNE PLUMBER 8061 08-APR-08 4000 50
8061 FEUERSTEIN PLUMBER 7839 27-FEB-10 4500 50
8100 PODER PLUMBER 8061 3750 50
SQL>
You can do this via a refcursor call or populate a user defined table and return it as follows:
create or replace
function getRef return sys_refcursor
is
l_ref sys_refcursor;
begin
open l_ref for
select 1 a, 'a' c from dual
union all
select 2 a, 'b' c from dual
union all
select 3 a, 'c' c from dual
union all
select 4 a, 'd' c from dual;
return l_ref;
end getRef;
/
select getref() from dual;
GETREF()
--------
A C
---------------------- -
1 a
2 b
3 c
4 d
--you'll notice this isn't the most user-friendly result set if you look at it in SQL Developer or whatno
--drop function getRef;
you can also use the 'table' if you are passing back a table collection as such
create or replace type lookup_row as
object ( a number, c varchar2(20) );
/
create or replace type lookups_tab as
table of lookup_row;
/
create or replace
function getUserDefinedTableType return lookups_tab
is
lTestTypeTable lookups_tab;
begin
SELECT lookup_row(a,c)
bulk collect INTO lTestTypeTable
from
(select 1 a, 'a' c from dual
union all
select 2 a, 'b' c from dual
union all
select 3 a, 'c' c from dual
union all
select 4 a, 'd' c from dual);
return lTestTypeTable;
end getUserDefinedTableType;
/
select * from table(getUserDefinedTableType());
--this returns it in a more user friendly manner
--http://www.oreillynet.com/pub/a/network/2003/01/22/feuerstein.html?page=2
--http://stackoverflow.com/questions/3150137/converting-oracle-query-into-user-defined-types-in-pl-sql/3152885#3152885
A C
---------------------- --------------------
1 a
2 b
3 c
4 d
have you tried:
myCursor := package_name.function_name(param,param);
this would have to be from within a test block or a stored procedure.