2012-10-29 52 views
0

以下是PL/SQL查詢的代碼,我必須獲取有資格教授特定課程的教師的姓名,當他們提供姓名時,連同他們教過本課程的次數和上一次(年和學期)當他們教這門課程。PL/SQL我想要MAX(O.CO_YEAR)的相應列。怎麼做?

我已經做了這個問題的大部分,但無法弄清楚如何獲得最大的相應細節(o.co_year),即長期

declare 
gname varchar2(20); 
count_id number(2); 
id varchar(20); 
year1 number(4); 

cursor abc // cursor 1 
    is 
     SELECT i.i_gname 
      into gname 
     FROM INSTRUCTOR I 
     WHERE i.i_id in (
     SELECT t.i_id FROM TeachingQualification T 
     WHERE t.c_id in (SELECT c.c_id FROM COURSE C 
     WHERE c.c_title = 'Advanced Database App')) ; 


cursor bcd // cursor two 
    is 
     select o.i_id, count(o.i_id), max(o.co_year) 
      into id, count_id, year1 
     from courseoffering o 
     where (o.i_id = i_id and o.c_id = 1234567) 
     group by o.i_id; 


Begin 
open abc; 
open bcd; 

loop 

FETCH abc into gname; 
exit when abc%NOTFOUND; 

FETCH bcd into id, count_id, year1; 
exit when bcd%NOTFOUND; 

DBMS_OUTPUT.PUT_LINE ('NAME: ' || gname || ' Number of times taught ' || count_id || ' Year ' || year1 ||); // want to output corresponding column details for the year1 attribute. 

end loop; 
close bcd; 
close abc; 
end; 

PL/SQL我想對應的列MAX(O.CO_YEAR)。怎麼做?

+0

你爲什麼要在PL/SQL中完成所有這些工作?你可以把它寫成一個單獨的SQL語句。 –

+0

是的,我知道,但它是一個大學任務,我想在PL/SQL中實現。 – Pravin

+0

你是什麼意思「想要輸出year1屬性的相應列詳細信息」。 ? – giorashc

回答

0

Oracle中的遊標可以有參數。詳情請參閱http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/sqloperations.htm#BABHICAF

它是如何威力工作在你的代碼:

cursor bcd(p_c_id courseoffering.c_id%type) // cursor two 
is 
    select o.i_id, count(o.i_id), max(o.co_year) 
     into id, count_id, year1 
    from courseoffering o 
    where (o.i_id = i_id and o.c_id = p_c_id) 
    group by o.i_id; 
+0

代碼運行,但在執行上述更改後沒有輸出。 – Pravin

+0

開始:'o。i_id = i_id'總是如此,可以被移除,但這不會神奇地使*你的*代碼工作。 –

+0

是的它沒有工作! – Pravin

2

是的,我知道,但它的一所大學的任務,我假設在PL/SQL中實現。

Blah!我寧願你的大學教你如何正確使用PLSQL和SQL,並給出一個有意義的任務。如果你可以在SQL中做某些事情,那麼在SQL中做。
另請參見:爲什麼您的遊標包含INTO關鍵字?你爲什麼需要一個循環?看來你只能期望1返回的價值?

我解剖你的代碼位:

--instructors who are qualified to teach a course 
SELECT i.i_gname --instructor name 
    FROM INSTRUCTOR I 
WHERE i.i_id IN (SELECT t.i_id --instructor_id 
        FROM TeachingQualification T 
        WHERE t.c_id in (SELECT c.c_id --course_id 
             FROM COURSE C 
             WHERE c.c_title = 'Advanced Database App')); 


--instructors who taught a course, with amount and last time 
SELECT o.i_id instructor_id, count(o.i_id) times_taught, max(o.co_year) last_time_taught 
    FROM courseoffering o 
WHERE o.c_id = 1234567 --course_id 
GROUP BY o.i_id; 

--all instructors (ID) who taught advanced database app, how many times, and last time 
--consider that this may produce NO_DATA_FOUND 
SELECT o.i_id instructor_id, count(o.i_id) times_taught, max(o.co_year) last_time_taught 
    FROM course c 
    JOIN courseoffering o 
    ON c.c_id = o.c_id 
WHERE c.c_title = 'Advanced Database App' 
GROUP BY o.i_id; 

-- i don't think teachingqualification is required. The last select providers instructor IDs. 
-- There is no need to go through that table, unless it would contain extra data you'd want to 
-- filter by. Since courseoffering is being queried, and it has instructors, it stands to reason 
-- that those instructor are qualified to teach the course. 
SELECT (SELECT i_gname FROM instructor WHERE i_id = o.i_id) instructor 
     ,count(o.i_id) times_taught 
     , max(o.co_year) last_time_taught 
    FROM course c 
    JOIN courseoffering o 
    ON c.c_id = o.c_id 
WHERE c.c_title = 'Advanced Database App' 
GROUP BY o.i_id; 

-- Look, if you do want a PLSQL block for this, go ahead. 
BEGIN 
    FOR r IN (SELECT (SELECT i_gname FROM instructor WHERE i_id = o.i_id) instructor 
        ,count(o.i_id) times_taught 
        , max(o.co_year) last_time_taught 
       FROM course c 
       JOIN courseoffering o 
       ON c.c_id = o.c_id 
       WHERE c.c_title = 'Advanced Database App' 
       GROUP BY o.i_id) 
    LOOP 
     DBMS_OUTPUT.PUT_LINE ('NAME: ' || r.instructor || ' Number of times taught ' || r.times_taught || ' Year ' || r.last_time_taught); 
    END LOOP; 
END; 

哦,請給你列一個有意義的名字。例如,將其稱爲instructor_id而不是i_id

我成立了一些示例數據:

create table course (id number(5,0), cname varchar2(50), constraint course_pk primary key (id)) 
/
create table courseoffering(id number(5,0), course_id number(5,0), instructor_id number(5,0), course_year number(5,0), constraint offering_pk primary key (id), constraint course_fk foreign key (course_id) references course (id)) 
/
insert into course values (1, 'Tech I'); 
insert into course values (2, 'Basic SQL'); 
insert into course values (3, 'Advanced SQL'); 
--Instructor 1 
insert into courseoffering values (1, 1, 1, 2009); --Tech I 
insert into courseoffering values (2, 1, 1, 2010); --Tech I 
insert into courseoffering values (3, 1, 1, 2011); --Tech I 
insert into courseoffering values (4, 2, 1, 2011); --Basic SQL 
insert into courseoffering values (5, 2, 1, 2012); --Basic SQL 
--Instructor 2 
insert into courseoffering values (6, 2, 2, 2008); --Basic SQL 
insert into courseoffering values (7, 2, 2, 2009); --Basic SQL 
insert into courseoffering values (8, 2, 2, 2010); --Basic SQL 
insert into courseoffering values (9, 3, 2, 2010); --Advanced SQL 
insert into courseoffering values (10, 3, 2, 2011); --Advanced SQL 
insert into courseoffering values (11, 3, 2, 2012); --Advanced SQL 
insert into courseoffering values (12, 1, 2, 2009); --Tech I 
insert into courseoffering values (13, 1, 2, 2010); --Tech I 
commit; 

運行此:

SELECT c.cname, o.instructor_id, count(o.instructor_id) times_taught, max(o.course_year) last_time_taught 
    FROM course c 
    JOIN courseoffering o 
    ON c.id = o.course_id 
GROUP BY c.cname, o.instructor_id 
ORDER BY c.cname, o.instructor_id; 

產地:

CNAME   INSTRUCTOR_ID TIMES_TAUGHT LAST_TIME_TAUGHT 
Advanced SQL 2    3    2012 
Basic SQL  1    2    2012 
Basic SQL  2    3    2010 
Tech I   1    3    2011 
Tech I   2    2    2010 

你甚至可以很容易地將所需要的數據到視圖。 不需要PLSQL。 SQL中只有幾行。如果你想在PLSQL中使用它,你仍然可以使用一個循環來覆蓋每個課程的多個教師,或者如果你將它縮小到一個課程和一個教師,則可以使用一些變量。總是最小化SQL和PLSQL上下文之間的切換。

+0

阿門!對不起,但這裏必須說。 –

+0

非常感謝TOM,這讓我大開眼界。結構化查詢和解釋的方式對我來說非常有用。再次感謝!!! – Pravin

相關問題