Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2008 Forums
 Transact-SQL (2008)
 PL/SQL Function to T-SQL Conversion Woes

Author  Topic 

FrankWoodall
Starting Member

1 Post

Posted - 2009-09-15 : 17:16:49
Project Background:
I just wanted to be honest and let you guys know that I am a student. I am not however looking for homework help . The project I am working on is a project I volunteered to do last semester to help out the director of my program. We offer several certificates and with the number of students in the program (350+) it was becoming tedious to track who has earned what by hand. That's where this project came in. It tracks student grades and determines if someone is eligible for a certificate. It has worked fantastically. I originally built it using oracle but due to some licensing and other issues (including some slight table redesign), the powers that be have decided that I get to migrate everything to SQL Server. Hooray for me.

Current Progress:
I've gotten all of the data migrated and started working on the stored procedures and functions when I realized that PL/SQL doesn't really work that well on SQL Server. hehe. I looked for some conversion tools, there aren't any to speak of, so I started doing it manually. That's when I came to discover that T-SQL isn't really anything like PL/SQL at all. I did some reading on these forums and others and it seems that you guys try to steer away from using cursors (something upon which my functions rely heavily) in favor of large SQL statements.

Problem Definition:
So my question is, taking into consideration the slight table redesigns and differences between oracle and sql server, would it be better to attempt to manually convert all of my SPs and Functions over to T-SQL or to rewrite them completely from scratch or to try and do them using SQL instead?

Example Function:
create or replace
Function cbnf_single
/* Certs by Number Function Single
Purpose:
Determine whether or not a student meets the core requirements
and has enough electives to qualify for a particular cert
Author:
Frank Woodall
*/
(
p_cert_id IN Varchar2,
p_student_id IN Varchar2
)
Return Number As
v_retVal Number := 1;
v_valid_start CERTIFICATES.VALID_START%Type;
v_required_class REQUIREMENTS.COURSE_ID%Type;
v_required_grade REQUIREMENTS.GRADE%Type;
v_mostRecentClassDate GRADES.SEMESTER_ID%Type := 0;

Cursor CertCursor Is
SELECT valid_start vstart, valid_end vend
FROM certificates
WHERE cert_id = p_cert_id;
c_CertCursor CertCursor%Rowtype;

Cursor ReqCursor Is
SELECT course_id cid, grade g
FROM requirements
WHERE cert_id = p_cert_id;
c_ReqCursor ReqCursor%Rowtype;

Cursor StuCursor (pi_student_id In Varchar2, pi_course_id In Varchar2) Is
SELECT grade g, semester_id semid
FROM grades
WHERE student_id = pi_student_id
AND course_id = pi_course_id;
c_StuCursor StuCursor%Rowtype;

Cursor ElecCursor(pi_cert_id In Varchar2) Is
SELECT elec_type etype, num_of_classes numClass
FROM Cert_elec_reqs
WHERE cert_id = p_cert_id;
c_ElecCursor ElecCursor%Rowtype;

Begin

Open CertCursor;
Fetch CertCursor
Into c_CertCursor;
dbms_output.put_line('Start Date: '||c_CertCursor.vstart);
dbms_output.put_line('End Date: '||c_CertCursor.vend);


Open ReqCursor;
Loop
Fetch ReqCursor
Into c_ReqCursor;
Exit When ReqCursor%NOTFOUND;

Open StuCursor(p_student_id, c_ReqCursor.cid);
Fetch StuCursor
Into c_StuCursor;
If StuCursor%FOUND Then
dbms_output.put_line(initcap('Required Class: ' || c_ReqCursor.cid ||
', Required Grade: ' || c_ReqCursor.g));

If c_StuCursor.g >= c_ReqCursor.g Then
dbms_output.put_line(initcap('Students grade for class ' ||
c_ReqCursor.cid || ': ' ||
c_StuCursor.g));
Else
dbms_output.put_line(initcap('Grade not high enough'));
Return 0;
End If; --End student grade > required grade if
Else
dbms_output.put_line(initcap('Class Not Found'));
Return 0;
End If;--end StuCursor%Found if
Close StuCursor;
End Loop;--End ReqCursor loop
Close ReqCursor;

dbms_output.put_line('Checking Electives');

Open ElecCursor(p_cert_id);
Loop
Fetch ElecCursor
Into c_ElecCursor;
Exit When ElecCursor%NOTFOUND;
v_retVal := she_date(p_student_id, c_ElecCursor.etype, c_ElecCursor.numClass, p_cert_id, c_CertCursor.vend);

If v_retVal = 0 Then
dbms_output.put_line('Elective not in right date range');
Close ElecCursor;
GoTo GoAgain;
End If;
End Loop;
Close ElecCursor;
<<GoAgain>>
Close CertCursor;
Return v_retVal;
End;


Here is a picture of the current tables and relationships. I figured this would be better than another wall of text.


I am open to any and all suggestions, even if it means I have to learn a new language or thought process. This is a fairly large project for me (probably chump change for you guys =P) and I'm working on it in my spare time. If one of you is willing to take this on, I'd be very appreciative. If you need any more information or specifics, fire away.

Thanks for finishing my novel,
Frank

SteveTR
Starting Member

7 Posts

Posted - 2009-09-22 : 14:39:11
Frank,
I wasn't able to view the picture of tables/relationships in IE or Mozilla, so you might need to post that in text form.
It's been about 10 years since I worked under Oracle, but if I read your procedure correctly, it's not doing anything complex except build nice text strings based on various conditions.
The first technique I would recommend is using the CASE statement. You can lookup the syntax on Books On Line, but this is basically an in-line IF statement that you can control the output (i.e. formatted text strings) based on a logical comparison.
For example, re-writing a bit of your code above becomes


SELECT grade as g, semester_id as semid,
CASE WHEN (grade > 3.0)
THEN 'Students grade for class =' + grade
ELSE 'Grade not high enough'
END as
FROM grades
WHERE student_id = @pi_student_id
AND course_id = @pi_course_id

The second tool I'd recommend is select into variable:

DECLARE @required_grade int
SET @required_grade = SELECT grade FROM requirements WHERE cert_id = 1234

This is useful for determining records counts SET @cnt = SELECT count(*) FROM table...

Long story short, I also recommend staying away from cursors, but there still is an order of events in T-SQL stored procedures, a logical progression of set-based activities if you will.






Go to Top of Page
   

- Advertisement -