Need for PL/SQL — declarative vs. procedural — anonymous blocks — debugging — a first program — code compilation — code execution — procedures & functions — PL/SQL in SQL — SQL in PL/SQL — cursors & loops — operators & built-in functions reference tables.
1 CREATE OR REPLACE PROCEDURE count_reviews
2 (author_param VARCHAR2)
3 IS
4 review_count NUMBER;
5 BEGIN
6 SELECT COUNT(*) INTO review_count
7 FROM book_reviews r, books b
8 WHERE b.isbn = r.isbn AND author = author_param;
9
10 IF review_count > 1 THEN
11 dbms_output.put_line('There are '
12 || review_count || ' reviews.');
12 ELSIF review_count = 1 THEN
14 dbms_output.put_line('There is 1 review.');
15 ELSE
16 dbms_output.put_line('There is no review.');
17 END IF;
18 END;
19 /
Note in the code above how:
EXEC count_reviews('Oscar Wilde')
EXEC count_reviews('Charles Dickens')
The last program we are going to write will display the number of reviews relevant to each author. Notice that the query may now return multiple rows. However, a SELECT...INTO... statement can only retrieve data from (at most) one tuple into individual variables.
Cursors3 provide a means to retrieve multiple rows into a buffer (when you OPEN the cursor) that can then be traversed sequentially (FETCH) to retrieve individual rows—until there is no more data (cur_revs%NOTFOUND becomes true).
CREATE OR REPLACE PROCEDURE count_by_author
IS
auth VARCHAR2(30);
cnt NUMBER;
CURSOR cur_revs IS
SELECT author, COUNT(author) AS revs_cnt
FROM books b, book_reviews r
WHERE b.isbn = r.isbn GROUP BY author;
BEGIN
OPEN cur_revs;
LOOP
FETCH cur_revs INTO auth, cnt;
EXIT WHEN cur_revs%NOTFOUND;
IF cnt = 1 THEN dbms_output.put_line('1 review for '
|| auth);
ELSE
dbms_output.put_line(cnt || ' reviews for ' || auth);
END IF;
END LOOP;
CLOSE CUR_REVS;
END;
/
Execute count_by_author, adding more data to the tables if necessary.
|
|
PL/SQL User's Guide and Reference:
//download-west.oracle.com/docs/cd/A91202_01/901_doc/appdev.901/a89856/toc.htm