Oracle PL/SQL Programming, 2nd Edition by Steve Feuerstein with Bill Pribyl This errata page lists errors outstanding in the most recent printing. If you have technical questions or error reports, you can send them to booktech@oreilly.com. (Please specify the printing date of your copy.) This page was last updated on August 20, 2002. Here's a key to the markup: [page-number]: serious technical mistake {page-number}: minor technical mistake : important language/formatting problem (page-number): language change or minor formatting problem ?page-number?: reader question or request for clarification CONFIRMED errors: (144) In the third line up from the bottom of the page: "evalutes" should read: "evaluates" (146) The paragraph beginning: "The PL/SQL run-time engine evalutes ..." should read: "The PL/SQL run-time engine evaluates ..." {163} Figure 6-1: The "arrows" should point to the right direction since the cursor is fetched into Program Variable(s), not the Program Variables are fetched to the cursor (errors point to the left). (188) Add to end of second to last paragraph on the page: In addition, if your query has more than one table in the FROM clause, then the OF clause will restrict locking to only those tables whose columns are referenced in the OF clause. {265} The 15th line in the code sample now reads: error_msg VARCHAR2 (300) := SQLERRM; Should read: error_msg VARCHAR2 (512) := SQLERRM; {282} In the middle of the page: Change /-- to -- Change old_company_rec.address1 = new_company_rec.address1 AND to old_company_rec.address1 = new_company_rec.address1 (414) The line that reads: "This number of months then bexcomes..." Should read: "This number of months then becomes..." {475} These lines: SQL> start updemp 1100 VICE-PRESIDENT SQL> start updemp 1100 PRESIDENT Should read: SQL> start updemp 1100 VICE-PRESIDENT 300000 SQL> start updemp 1100 PRESIDENT 200000 (523) In Figure 16-2, the fourth-to-last line now reads: DBMS_OUTPUT.PUT.LINE Should read: DBMS_OUTPUT.PUT_LINE (525) In the last sentence of third paragraph, the footnote marker for "Booch diagram" is way up just under the line above. It should be next to "diagram." (802) In the second to last paragraph, change: "you will be permitted" to: "you are permitted" (564) Last line; ADD_MONTHS ('28-FEB-1994', 2) ==> 30-APR-1993 should read ADD_MONTHS ('28-FEB-1994', 2) ==> 30-APR-1994 (956) The fourth line of READ_ONLY section now reads: "...that transactions start." Should read: "...that transaction's start." {Diskette} There is an error in the code on the diskette that is correct in the book on page 211. The code should read: FUNCTION next_task RETURN task.task_id%TYPE IS /* Cursor of all open tasks, assigned and unassigned */ CURSOR task_cur IS SELECT task_id FROM task WHERE task_status = 'OPEN' ORDER BY task_priority, date_entered DESC; /* The record for the above cursor */ task_rec task_cur%ROWTYPE; /* || An exception for error ORA-00054: || "resource busy and acquire with NOWAIT specified" */ record_locked EXCEPTION; PRAGMA EXCEPTION_INIT (record_locked, -54); /* || Variables which determine whether function should continue || to loop through the cursor's records. */ found_unassigned_task BOOLEAN := FALSE; more_tasks BOOLEAN := TRUE; /* The primary key of the unassigned task to be returned */ return_value task.task_id%TYPE := NULL; BEGIN /* Open the cursor and start up the loop through its records */ OPEN task_cur; WHILE NOT found_unassigned_task AND more_tasks LOOP /* Fetch the next record. If nothing found, we are done */ FETCH task_cur INTO task_rec; more_tasks := task_cur%NOTFOUND; IF more_tasks THEN /* || A record was fetched. Create an anonymous block within || the function so that I can trap the record_locked || exception and still stay inside the cursor loop. */ BEGIN /* Try to get a lock on the current task */ SELECT task_id INTO return_value FROM task WHERE task_id = task_rec.task_id FOR UPDATE OF task_id NOWAIT; /* || If I get to this line then I was able to get a lock || on this particular task. Notice that the SELECT INTO || has therefore already set the function's return value. || Now set the Boolean to stop the loop. */ found_unassigned_task := TRUE; EXCEPTION WHEN record_locked THEN /* Record was already locked, so just keep on going */ NULL; END; END IF; END LOOP; /* || Return the task id. Notice that if an unassigned task was NOT || found, I will simply return NULL. */ CLOSE task_cur; RETURN return_value; EXCEPTION /* || General exception handler for the function: if an error occurred, || then close the cursor and return NULL for the task ID. */ WHEN OTHERS THEN CLOSE task_cur; RETURN NULL; END; {961} under the heading UTL_FILE, the author says that "You can, therefore, interact with operating system files both on the local workstation(client) and on the server disks." This, I believe, is incorrect or at least misleading. Please look at this short thread for further discussion: http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&threadm=cb7b347afd620c2ae d0d8fa29d5c12dd.29848%40mygate.mailgate.org&rnum=1&prev=/groups%3Fsafe%3Dima ges%26ie%3DISO-8859-1%26as_umsgid%3Dcb7b347afd620c2aed0d8fa29d5c12dd.29848%4 0mygate.mailgate.org%26lr%3D%26hl%3Den {diskette} These lines (from the updemp.sql script on page 475): SQL> start updemp 1100 VICE-PRESIDENT SQL> start updemp 1100 PRESIDENT Should read: SQL> start updemp 1100 VICE-PRESIDENT 300000 SQL> start updemp 1100 PRESIDENT 200000 {diskette} The code for recomp.sql was changed in the book on page 823 but not on the diskette. The code on the diskette should also be the following: SET PAGESIZE 0 SET LINESIZE 80 COLUMN command_line1 FORMAT A75 COLUMN command_line2 FORMAT A75 SPOOL recomp.cmd SELECT 'ALTER '|| DECODE (object_type, 'PACKAGE BODY', 'PACKAGE', object_type) || ' '|| object_name || ' ' || DECODE (object_type, 'PACKAGE', 'COMPILE SPECIFICATION;', 'PACKAGE BODY', 'COMPILE BODY;' , 'COMPILE;') command_line1, 'SHOW ERRORS' command_line2 FROM user_objects WHERE object_type IN ('PACKAGE', 'PACKAGE BODY', 'FUNCTION', 'PROCEDURE') AND status = 'INVALID' ORDER BY DECODE (object_type, 'PACKAGE', 1, 'PACKAGE BODY', 4, 'FUNCTION', 2, 'PROCEDURE', 3) / SPOOL OFF SPOOL recomp.lis START recomp.cmd {diskette} db2tab2.sql on companion disk is incorrect in the following way: company_table.company_id (next_row) := company_rec.company_id; should read company_table(next_row) .company_id := company_rec.company_id; etc...