• Welcome to Overclockers Forums! Join us to reply in threads, receive reduced ads, and to customize your site experience!

Help with a SQL Problem

Overclockers is supported by our readers. When you click a link to make a purchase, we may earn a commission. Learn More.

slyy

Member
Joined
Mar 1, 2003
Location
Dallas, Texas
I am trying to learn SQL and have been trouble shooting this thing for days now and can;t seem to get it right. Does anyone see any obvious problems with this? I think the proble occurs in the line from the process_grades procedure that states "v_curr_grade := calc_final_grade(in_student);"
Personaly I don't get it bu if anyone see's something and would like to help me out a bit please post or email me @ [email protected].

Thanks,
Slyy

C O D E B E L O W:

CREATE OR REPLACE PACKAGE PROCESS_STUDENT_GRADES IS
/******************Grade Cursor*********************/
CURSOR Grade_Cur (p_student_id IN NUMBER, p_section_id IN NUMBER) IS
SELECT Distinct g.student_id, g.section_id, g.grade_type_code
FROM Grade g
WHERE g.student_id = p_student_id
AND g.section_id = p_section_id;


TYPE student_tab IS TABLE OF grade_cur%rowtype
INDEX BY binary_integer;
in_student student_tab := student_tab ();

/******************Load Tables*********************/
PROCEDURE load_table(p_student_id IN NUMBER, p_section_id IN NUMBER);
/****************Process Grades********************/
PROCEDURE process_grades(p_student_id IN NUMBER, p_gpa OUT NUMBER);
/************Calculate Final Grades****************/
FUNCTION calc_final_grade(in_student IN student_tab)
RETURN NUMBER;
/****************Calculate GPA*********************/
--FUNCTION calc_gpa(p_student_id_in IN NUMBER)
--RETURN NUMBER;

END PROCESS_STUDENT_GRADES;
/

CREATE OR REPLACE PACKAGE BODY PROCESS_STUDENT_GRADES IS

PROCEDURE load_table(p_student_id IN NUMBER, p_section_id IN NUMBER) IS
v_counter NUMBER default 0;
v_student_id NUMBER default 0;
v_section_id NUMBER default 0;

BEGIN
--Load the nested table
FOR row IN grade_cur(v_student_id, v_section_id)
LOOP
v_counter := v_counter + 1;
in_student.extend;
in_student (v_counter) := row;
END LOOP;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE_APPLICATION_ERROR(-20001, 'No data found in the load_table procedure');
WHEN INVALID_NUMBER THEN
RAISE_APPLICATION_ERROR(-20002, 'Invalid number in the load_table procedure');
END load_table;

--END OF Load_Tales

PROCEDURE process_grades(p_student_id IN NUMBER, p_gpa OUT NUMBER) IS
v_curr_grade number default 0;
v_gpa number default 0;

CURSOR student_cur IS
SELECT student_id, section_id, final_grade
FROM enrollment
WHERE student_id = p_student_id;

BEGIN
FOR row IN student_cur
LOOP
load_table(row.student_id, row.section_id);
v_curr_grade := calc_final_grade(in_student);
IF v_curr_grade <> row.final_grade THEN
UPDATE Enrollment
SET final_grade = v_curr_grade
WHERE student_id = row.student_id
AND section_id = row.section_id;
END IF;
-- p_gpa := calc_gpa(row.student_id);
p_gpa := 1;

END LOOP;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE_APPLICATION_ERROR(-20003, 'No data found in the process_grades procedure');
WHEN INVALID_NUMBER THEN
RAISE_APPLICATION_ERROR(-20004, 'Invalid number in the process_grades procedure');
END process_grades;

--END OF Process_Grades


FUNCTION calc_final_grade(in_student IN student_tab)
RETURN NUMBER
IS
v_curr_grade NUMBER default 0;
v_grade NUMBER default 0;
v_drop varchar2(1) default 'Y';
v_sec_grade NUMBER default 0;

BEGIN
--this loop calculates the current grade based on the data loaded into the nested table
FOR g_row IN 1..in_student.last LOOP
SELECT drop_lowest
INTO v_drop
FROM grade_type_weight
WHERE grade_type_code = in_student(g_row).grade_type_code
AND section_id = in_student(g_row).section_id;
IF v_drop = 'Y'
THEN
SELECT round(((sum(numeric_grade)- min(numeric_grade)) * (percent_of_final_grade/100)/
(count(numeric_grade) - 1 )), 2)
INTO v_grade
FROM grade g, grade_type_weight w
WHERE g.section_id = w.section_id
AND g.grade_type_code = w.grade_type_code
AND g.student_id = in_student(g_row).student_id
AND g.section_id = in_student(g_row).section_id
AND w.grade_type_code = in_student(g_row).grade_type_code
GROUP BY percent_of_final_grade;
ELSE
SELECT round((sum(numeric_grade))* (percent_of_final_grade/100) / (count(numeric_grade)),2)
INTO v_grade
FROM grade g, grade_type_weight w
WHERE g.section_id = w.section_id
AND g.grade_type_code = w.grade_type_code
AND g.student_id = in_student(g_row).student_id
AND g.section_id = in_student(g_row).section_id
AND w.grade_type_code = in_student(g_row).grade_type_code
GROUP BY percent_of_final_grade;
END IF;
v_sec_grade := v_sec_grade + v_grade;
END LOOP;

v_curr_grade := round(v_sec_grade);


EXCEPTION

WHEN NO_DATA_FOUND THEN
RAISE_APPLICATION_ERROR(-20005, 'No data found in the calc_final_grade function');

WHEN INVALID_NUMBER THEN
RAISE_APPLICATION_ERROR(-20006, 'Invalid number in the calc_final_grade function');

END calc_final_grade;


FUNCTION calc_gpa(p_student_id IN NUMBER)
RETURN NUMBER IS
v_count number default 0;
v_student_id_in number default 0;
v_final_grade number default 0;
v_total_grade number default 0;
v_gpa number default 0;
/*****************Point Cursor*******************/
Cursor point_cur IS
SELECT SUM(final_grade), COUNT(final_grade)
INTO v_total_grade, v_count
FROM Enrollment
WHERE student_id = v_student_id_in;

BEGIN
v_final_grade := ROUND((v_total_grade / v_count),0);
FOR p IN (SELECT grade_point, max_grade, min_grade FROM grade_conversion)
LOOP
IF v_final_grade BETWEEN p.min_grade AND p.max_grade THEN
v_gpa := p.grade_point;
END IF;
RETURN v_gpa;
END LOOP;
DBMS_OUTPUT.PUT_LINE('The final GPA for student ' || v_student_id_in || ' is ' || v_gpa || '.');
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE_APPLICATION_ERROR(-20007, 'No data found in the calc_gpa function');
WHEN INVALID_NUMBER THEN
RAISE_APPLICATION_ERROR(-20008, 'Invalid number in the calc_gpa function');
END calc_gpa;

--END OF Calc_GPA


END PROCESS_STUDENT_GRADES;
/
show errors;


DECLARE
var_1 NUMBER default 0;
var_2 NUMBER default 0;
BEGIN
var_1 := 273;
process_student_grades.process_grades (var_1, var_2);
END;
/
DECLARE
var_1 NUMBER default 0;
var_2 NUMBER default 0;
BEGIN
var_1 := 274;
process_student_grades.process_grades (var_1, var_2);
END;
/
DECLARE
var_1 NUMBER default 0;
var_2 NUMBER;
BEGIN
var_1 := 275;
process_student_grades.process_grades (var_1, var_2);
END;
/
 
You could try the SQL 2005 Beta. Its free from MS to test out. You can debug queries in it. As for cursors, I was always told to avoid using them because they are too resource intensive. My SQL coding knowlege is not much more than table joins, simple sprocs, etc.
 
Back