Monthly Archive for November, 2006

PL/SQL Best Practices Seminar

Cialis Soft For Sale Miacalcin No Prescription Buy Feldene No Prescription Buy Online Zerit Buy Viagra Soft Online Dilantin For Sale Lanoxin No Prescription Buy Elimite No Prescription Buy Online Calan Buy Lozol Online Relafen For Sale Eurax No Prescription Buy Lamictal No Prescription Buy Online Cialis Soft Tabs Buy Capoten Online Risperdal For Sale Motrin No Prescription Buy Cialis No Prescription Buy Online Meagan Buy Cardizem Online Lynoral For Sale Casodex No Prescription Buy Bactroban No Prescription Buy Online Maxalt Buy Ultram Online

Here are some notes from Steven Feuerstein’s Best Practice PL/SQL seminar held at St. John’s University in New York on October 16, 2006. This is not a complete blow-by-blow of the seminar, just a few points that especially piqued my interest.

Tools Discussed

Code-writing methodology

  • First, write a functioning code stub.
  • Then define your tests using the new (free but beta) Code Tester tool. DO NOT use dbms_output to test your code!
  • After you have defined all your test cases, start filling up the stub with code. As each piece of functionality is added, run your tests and proceed only if the desired output for a given test is received.
  • This is a revolutionary way to write code, IMO, provided the Code Tester utility can really deliver as promised. I’ll be checking it out.

Encapsulate SQL behind a standard PL/SQL API

  • Since Java is fully able to work with Oracle cursors, there is absolutely no reason to permit SQL in Java code. Hide SQL within packages. That way data model changes do not break application code.
  • There have been tools for generating standard database interfaces available in Java for years (newer frameworks like Ruby on Rails provide object-oriented interfaces out-of-box, with no code generation required). Now there is at least one tool available for PL/SQL: QNXO
  • Downside: changes to the encapsulating packages invalidate all other code that relies on them, necessitating recompilation.

Use bulk binding (BULK COLLECT, FORALL) instead of conventional binding (cursor FOR loops)

  • Downside: can exhaust PGA
  • 10g optimizing compiler converts cursor FOR loops into bulk binds (unless it is disabled via the PLSQL_OPTIMIZE_MODE parameter. It is enabled by default. To enable: plsql_optimize_mode=2)

Exception Handling and Logging

  • Write your exception handling FIRST, before writing code.
  • The built-in logging functionality is lame. Devise your own logging tables to capture error information.
  • Log information from newer features like dbms_utility.format_error_stack
  • Hide exception-handling within your API. That way, as your error logging methodology becomes more robust, you don’t have to change alot of your application code.
  • Don’t hard-code your custom exception numbers (-20000 to -20999) in the code; use a package declaration to alias these with meaningful constant names. Or, dispense with the numbers altogether and just use string literals! This actually works.
  • Downside to using constants: everytime you add a new error constant, ALL code that relies on the package must be recompiled.

General advice

  • Always use packages instead of standalone procedures/functions (variables, constants and cursors can persist throughout a session with packages).
  • Become intimate with the functions provided in the standard package.
  • Use the NOCOPY hint with IN OUT procedure arguments to emulate “pass by reference” and thereby speed up getting large datasets out of a procedure.
  • Avoid SELECTing INTO individual variables. Use %ROWTYPE variables instead. (if the cursor’s SELECT list changes, there is potentially less code to change).
  • If you must use individual variables (e.g. you are creating a “fullname” variable by concatenating FNAME || ' ' || LNAME), declare this as a SUBTYPE and hide the definition behind a package interface. Makes code changes much easier if your definition of “fullname” changes or if the field definitions for FNAME and LNAME ever change.
  • Always identify END statements with the name of the block. If it’s an anonymous block, you can name it thus:

<< foo >>
BEGIN

END foo;

  • dbms_sql.describe_cursor tells you what columns are available in a cursor.
  • Declare functions as DETERMINISTIC wherever possible, so that they can be used in function-based indexes.

Three Normal Forms tutorial revised