Mike Ault White Paper

White Paper

WHITE PAPER COPYRIGHT © 2002 ROBO BOOKS. ALL RIGHTS RESERVED.

PAGE 2

Notice
While ROBO Books makes every effort to ensure the information presented in this white paper is accurate and without error, ROBO Books, its authors and its affiliates takes no responsibility for the use of the information, tips, techniques or technologies contained in this white paper. The user of this white paper is solely responsible for the consequences of the utilization of the information, tips, techniques or technologies reported herein.

Change History
Release 1.0 Date 8/2/2002 Description Initial release in ROBO Books Format By Michael R. Ault

WHITE PAPER COPYRIGHT © 2002 ROBO BOOKS. ALL RIGHTS RESERVED.

PAGE 3

Table Of Contents
Notice....................................................................................................................................3 Change History..............................................................................................................................3 Table Of Contents................................................................................................................4 Introduction..........................................................................................................................5 PL/SQL Coding Guidelines.................................................................................................5 Headers..........................................................................................................................................5
Example PL/SQL Header:.....................................................................................................................................5

Create Command in PL/SQL........................................................................................................5 Cursor Declaration in PL/SQL......................................................................................................6 Variable Definitions in PL/SQL....................................................................................................7 Body Definitions in PL/SQL:........................................................................................................8 Exceptions in PL/SQL.................................................................................................................11 Full PL/SQL Example:................................................................................................................12 SQLPlus Coding Guidelines.............................................................................................13 Headers........................................................................................................................................13 Variable Declaration in SQLPlus................................................................................................13 Column Definitions in SQLPlus.................................................................................................14 Special Use Commands in SQLPLus..........................................................................................14
Set command definitions in SQLPlus..................................................................................................................14 Special Calls in SQLPlus:....................................................................................................................................15

Spool Commands in SQLPlus:....................................................................................................15 Processing Commands in SQLPlus:............................................................................................15 After Process Commands............................................................................................................16 Full SQLPlus Example:...............................................................................................................17

WHITE PAPER COPYRIGHT © 2002 ROBO BOOKS. ALL RIGHTS RESERVED.

PAGE 4

GUIDELINES

Introduction
In order to provide easy to understand and maintain PL/SQL and SQLPlus code, it is necessary to follow coding guidelines and standards. To date, no guidelines have been presented resulting in a polyglot of coding styles ranging from eminently satisfying to wholly inadequate. This document will present some suggested PL/SQL and SQLPlus coding standards. As a general rule, key words in SQLPlus and PL/SQL should be capitalized and all other items (except case sensitive selection criteria) lower case. Comments can be upper, lower or sentence case, sentence case is suggested for readability.

PL/SQL Coding Guidelines
Headers
All PL/SQL and SQLPlus scripts should contain a header that identifies the coder, date of last revision, component the script applies to and any “need to knows” about the code.

Example PL/SQL Header:
-- - Title: (name of script) - - Used by Application: (application the procedure/function/pacakage belongs to) - - Purpose: (general purpose of script - keep it short) - - Limitations: (any prerequisites, privileges, grants, etc.) -- - Inputs: (list required inputs to procedure,function,etc) - - Outputs: (list any output variables and their type) -- - History: - - Who: What: Date: - -(list changes to file) - - Notes: - - (List any special notes applicable to procedure, function, etc.) --

Create Command in PL/SQL
The first part of any stored procedure, package, package body or function in PL/SQL is the CREATE command. The create command should use the OR REPLACE clause to ensure that new updates get loaded over old code. The variable declarations n the CREATE command should be placed on separate lines for readability and the AS keyword should also reside on a separate line. All IN-only variables should
WHITE PAPER COPYRIGHT © 2002 ROBO BOOKS. ALL RIGHTS RESERVED. PAGE 5

GUIDELINES

come first followed by the IN OUT or OUT variables. For anonymous blocks, the CREATE command is replaced with the DECLARE keyword. Example: CREATE OR REPLACE PROCEDURE AddRmaNote ( hv_eventid IN event.evntid%TYPE, hv_actseqnbr IN act.actseqnbr%TYPE, hv_user IN indiv.cuidnbr%TYPE, hv_notes IN VARCHAR2, hv_status IN OUT NUMBER ) AS - - OR - DECLARE

Cursor Declaration in PL/SQL
Following the Header in PL/SQL will be the DECLARE for anonymous blocks, or the CREATE OR REPLACE command, the in/out variable declaration and then the cursor declaration: Example: *Header* *Create or Declare* CURSOR get_one IS (cursor definition); CURSOR get_two IS (cursor definition); The cursor definition should follow this general structure: CURSOR (cursor name) IS SELECT (list of columns) FROM (list of tables WHERE (list of clauses) ORDER BY (list of columns) ; For example: CURSOR cons_cursor IS SELECT owner, constraint_name,
WHITE PAPER COPYRIGHT © 2002 ROBO BOOKS. ALL RIGHTS RESERVED. PAGE 6

GUIDELINES

decode(constraint_type,'C','CK_','V','DF_'), table_name, search_condition, r_owner, r_constraint_name, delete_rule FROM user_constraints WHERE owner not in ('SYS','SYSTEM') and constraint_type in ('C','V') ORDER BY owner, constraint_type ; This format is easy to read and allows a quick scan of required inputs or outputs.

Variable Definitions in PL/SQL
After the cursor definitions in PL/SQL should come the variable definitions, ROWTYPE, TYPE, TABLE and RECORD first followed by local definition variables. These definitions should be tab separated to make them readable. Example: *Header* *Create or Declare* *Cursors* - - Table Definitions -TYPE numtab IS TABLE OF NUMBER INDEX BY BINARY_INTEGER; tab_counts numtab; user_counts numtab; -- - Record Definitions -TYPE UserRecType IS RECORD (userno NUMBER(2), dname CHAR(14), loc CHAR(23)); user_rec UserRecType; -- - Rowtype Definitions -table_rec dba_tables%ROWTYPE -- - Type Definitions -tab_nam user_constraints.table_name%TYPE; cons_owner user_constraints.owner%TYPE;
WHITE PAPER COPYRIGHT © 2002 ROBO BOOKS. ALL RIGHTS RESERVED. PAGE 7

GUIDELINES

cons_name user_constraints.constraint_name%TYPE; -- - Local Variable Definitions -cons_type varchar2(11); all_columns varchar2(2000); counter integer:=0; cons_nbr integer;

Body Definitions in PL/SQL:
The body of the PL/SQL procedure consists of several possible constructs such as loops, selects, beginend blocks and exceptions. These constructs should use tab indenting (if they are small) or space indenting (if they are large) to promote readability. Clauses in SELECT, INSERT or UPDATE commands should be placed on separate lines and slightly indented under the parent command. All loop contents should be indented inside of each loop construct. All block contents should be indented inside each BEGIN-END pair. Procedures should not exceed one hundred lines in length. This is accomplished through compartmentalization of code into sub-procedures and functions and through the use of cursors for multiple select statements. A line of code is considered to be a single command, so even though a large select, insert or update type command spans several physical lines, it is only one line of code. For example, if the following procedure has been built in your schema or you have execute privilege on it, the procedure can be called from other procedures to provide insert processing into i_temp: CREATE OR REPLACE PROCEDURE write_ind( p_line INTEGER, p_owner varchar2, p_name VARCHAR2, p_string VARCHAR2) IS BEGIN INSERT INTO i_temp ( lineno, id_owner, id_name, text) VALUES ( p_line, p_owner, p_name, p_string); END; By using these sub-procedures you can reduce the space requirements in your procedures. There should be comments added into the processing body to show functions and explain special processing (if needed). Example script fragment showing use of sub-procedures, comments and indenting:

WHITE PAPER COPYRIGHT © 2002 ROBO BOOKS. ALL RIGHTS RESERVED.

PAGE 8

GUIDELINES

*Header* *Create or Declare* *Cursors* *Declarations* BEGIN db_lineno:=db_lineno+1; SELECT 'CREATE DATABASE '||value into db_string FROM v$parameter WHERE name='db_name' ; write_ind(db_lineno,db_string); db_lineno:=db_lineno+1; -- - Select the following command from dual since it isn’t stored -SELECT 'CONTROLFILE REUSE' into db_string FROM dual ; write_ind(db_lineno,db_string); db_lineno:=db_lineno+1; -- - Select the following command from dual since it isn’t stored -SELECT 'LOGFILE (' into db_string FROM dual ; write_ind(db_lineno,db_string); COMMIT; -- - Get redo log thread information -IF thread_cursor%ISOPEN THEN CLOSE thread_cursor; OPEN thread_cursor; ELSE OPEN thread_cursor; END IF; LOOP FETCH thread_cursor INTO thrd,grp; EXIT WHEN thread_cursor%NOTFOUND; db_lineno:=db_lineno+1; db_string:= 'THREAD '||thrd||' GROUP '||grp||' ('; write_ind(db_lineno,db_string); -- - Get Thread, group, member information -IF mem_cursor%ISOPEN THEN CLOSE mem_cursor;
WHITE PAPER COPYRIGHT © 2002 ROBO BOOKS. ALL RIGHTS RESERVED. PAGE 9

GUIDELINES

OPEN mem_cursor(grp); ELSE OPEN mem_cursor(grp); END IF; db_lineno:=db_lineno+1; begin_count:=db_lineno; LOOP FETCH mem_cursor INTO grp_member; EXIT WHEN mem_cursor%NOTFOUND; IF begin_count=db_lineno THEN db_string:=''''||grp_member||''''; write_ind(db_lineno,db_string); db_lineno:=db_lineno+1; ELSE db_string:=','||'''||grp_member||'''; write_ind(db_lineno,db_string); db_lineno:=db_lineno+1; END IF; END LOOP; db_lineno:=db_lineno+1; db_string:=' )'; write_ind(db_lineno,db_string); END LOOP; db_lineno:=db_lineno+1; SELECT ')' INTO db_string FROM dual ; write_ind(db_lineno,db_string); COMMIT; -- - Get datafile information for the SYSTEM tablespace -IF dbf_cursor%ISOPEN THEN CLOSE dbf_cursor; OPEN dbf_cursor; ELSE OPEN dbf_cursor; END IF; begin_count:=db_lineno; LOOP FETCH dbf_cursor INTO filename, sz; EXIT WHEN dbf_cursor%NOTFOUND; IF begin_count=db_lineno THEN db_string:='DATAFILE '||''''||filename||''''||' SIZE '||sz||' REUSE'; ELSE db_string:=','||''''||filename||''''||' SIZE '||sz||' REUSE'; END IF; db_lineno:=db_lineno+1; write_ind(db_lineno,db_string); END LOOP; COMMIT; -- - Archive log data is stored as either a true or false setting, so we must decode -WHITE PAPER COPYRIGHT © 2002 ROBO BOOKS. ALL RIGHTS RESERVED. PAGE 10

GUIDELINES

SELECT decode(value,'TRUE','ARCHIVELOG','FALSE','NOARCHIVELOG') INTO db_string FROM v$parameter WHERE name='log_archive_start' ; db_lineno:=db_lineno+1; write_ind(db_lineno,db_string); SELECT ';' INTO db_string FROM dual ; db_lineno:=db_lineno+1; write_ind(db_lineno,db_string); CLOSE dbf_cursor; CLOSE mem_cursor; CLOSE thread_cursor; COMMIT; END;

Exceptions in PL/SQL
Exceptions usually come at the end of the PL/SQL construction, or, at the end of a BEGIN-END construct. The contents of the exception clause should be indented beneath the EXCEPTION keyword and follow the other indention rules. All EXCEPTION sections should include a WHEN OTHERS exception. Example: *Header* *Create or Declare* *Cursors* *Declarations* *Body* EXCEPTION WHEN NO_DATA_FOUND THEN INSERT INTO dba_temp VALUES ( stat_name,0); COMMIT; WHEN ZERO_DIVIDE THEN INSERT INTO dba_temp VALUES ( stat_name,0); COMMIT; WHEN OTHERS THEN NULL;

WHITE PAPER COPYRIGHT © 2002 ROBO BOOKS. ALL RIGHTS RESERVED.

PAGE 11

GUIDELINES

Full PL/SQL Example:
-- - Title: AddRmaNote - - Used by Application: RMA GUI - - Purpose: Add RMA notes - - Limitations: None -- - Inputs: eventid, actseqnbr, user, notes - - Outputs: status -- - History: - - Who: What: Date: - - Mike Ault Added Header 4/16/96 - - Notes: - - None -CREATE OR REPLACE PROCEDURE AddRmaNote ( hv_eventid IN event.evntid%TYPE, hv_actseqnbr IN act.actseqnbr%TYPE, hv_user IN indiv.cuidnbr%TYPE, hv_notes IN VARCHAR2, hv_status IN OUT NUMBER ) AS -- - Local Variables -leid NUMBER(10); date1 DATE; -- - Body -BEGIN hv_status := 0; leid := 0; BEGIN SELECT fk_leleid INTO leid FROM indiv WHERE cuidnbr = hv_user ; EXCEPTION WHEN OTHERS THEN hv_status := 1; END; SELECT sysdate INTO date1 FROM dual; IF ( leid > 0 ) THEN INSERT INTO actvy_rmk ( actvyrmkdt,
WHITE PAPER COPYRIGHT © 2002 ROBO BOOKS. ALL RIGHTS RESERVED. PAGE 12

GUIDELINES

actvyrmktxt, fk_actfk_eventevnt, fk_actactseqnbr, fk_indivfk_leleid ) VALUES ( date1, hv_notes, hv_eventid, hv_actseqnbr, leid ); END IF; COMMIT; END AddRmaNote;

SQLPlus Coding Guidelines
Headers
All PL/SQL and SQLPlus scripts should contain a header that identifies the coder, date of last revision, component the script applies to and any “need to knows” about the code. Example SQLPlus header: REM REM Title: (name of script) REM Purpose: (general purpose of script - keep it short) REM Limitations: (any prerequisites, grants, privileges required) REM REM Inputs: (List required inputs to script) REM Outputs: List results from script) REM REM History: REM Who: What: Date: REM (List of changes to file) REM Notes: REM (list any special notes applicable to script)

Variable Declaration in SQLPlus
Following the header in a SQLPlus script should be any variable DEFINE or ACCEPT /PROMPT statements. Example: * Header *
WHITE PAPER COPYRIGHT © 2002 ROBO BOOKS. ALL RIGHTS RESERVED. PAGE 13

GUIDELINES

DEFINE INPUT1 = &1; DEFINE INPUT2 = &2; ACCEPT INPUT3 PROMPT ‘Enter value for INPUT3: ‘

Column Definitions in SQLPlus
Following the variable definitions in SQLPlus should come the column format definitions. The different sections of the column commands should be tab separated to promote readability (where possible). Example: COLUMN owner COLUMN cluster_name COLUMN tablespace_name COLUMN pct_free COLUMN pct_used COLUMN key_size FORMAT a10 FORMAT a15 HEADING "Cluster" FORMAT a15 HEADING "Tablespace" FORMAT 999999 HEADING "% Free" FORMAT 999999 HEADING "% Used" FORMAT 999999 HEADING "Key Size"

Special Use Commands in SQLPLus
Commands such as BREAK and COMPUTE should follow the column definitions. Example: * Header* *Variables* *Columns* BREAK ON owner ON tablespace_name ON cluster_name ON table_name COMPUTE SUM OF bytes ON table_name

Set command definitions in SQLPlus
Set commands are used to define the environment for SQLPlus scripts. The SET commands should follow the break and compute definitions. If there are only a few (less than 5) SET commands, they can be grouped on a single line, if there are more than 5, try to limit them to 5 per line or whatever is most readable: Example: * Header* *Variables* *Columns* *Break and Computes* SET FEED OFF FLUSH OFF VERIFY OFF PAGES 58 LINES 130

WHITE PAPER COPYRIGHT © 2002 ROBO BOOKS. ALL RIGHTS RESERVED.

PAGE 14

GUIDELINES

Special Calls in SQLPlus:
Any special calls such as header generators or special variable definitions should follow the set commands: * Header* *Variables* *Columns* *Break and Computes* * Set commands* START title132 "TABLE GRANTS BY OWNER AND TABLE" * Header* *Variables* *Columns* *Break and Computes* * Set commands* COLUMN dbname NEW_VALUE db NOPRINT SELECT value dbname FROM v$parameter WHERE name=‘db_name’;

Spool Commands in SQLPlus:
To generate file output from SQLPlus, the SPOOL command is used. This command should be the last command before the actual SELECT that generates the output. Example: * Header* *Variables* *Columns* *Break and Computes* * Set commands* * Special Calls* SPOOL rep_out\&db\db_rct.sql

Processing Commands in SQLPlus:
Processing commands such as UPDATE, DELETE, INSERT and SELECT should follow the SPOOL command if it is present (Generally, SPOOL will be used with selects, but may be used for logging purposes with other commands.) The processing commands should have one clause per line with any lists of tables, columns or variables broken across multiple lines for readability. Example: * Header*
WHITE PAPER COPYRIGHT © 2002 ROBO BOOKS. ALL RIGHTS RESERVED. PAGE 15

GUIDELINES

*Variables* *Columns* *Break and Computes* * Set commands* * Special Calls* * Spool command * SELECT owner, table_name, grantee, grantor, privilege, grantable FROM dba_tab_privs WHERE OWNER NOT IN ('SYS','SYSTEM') ORDER BY owner, table_name, grantor, grantee;

After Process Commands
After process commands are used to turn off computes, breaks, column definitions and other general cleanup such as securing spooling. If the script immediately exits SQLPLUS the only cleanup required may be the SPOOL OFF command. If more scripts will be run, it is suggested that columns be turned off, computes turned off and breaks turned off. Any SET commands should be reversed if more processing is to be done. Example: * Header* *Variables* *Columns* *Break and Computes* * Set commands* * Special Calls* * Spool command * *Processing Commands* SPOOL OFF EXIT - - OR - * Header* *Variables* *Columns* *Break and Computes* * Set commands* * Special Calls* * Spool command *
WHITE PAPER COPYRIGHT © 2002 ROBO BOOKS. ALL RIGHTS RESERVED. PAGE 16

GUIDELINES

* Processing Commands * SPOOL OFF UNDEF input1 UNDEF input2 CLEAR BREAKS CLEAR COLUMNS CLEAR COMPUTES SET LINESIZE 80 PAGES 20 VERIFY ON FEEDBACK ON PAUSE Press enter to continue

Full SQLPlus Example:
REM REM NAME: GRANTS7.sql REM REM PURPOSE: Produce report of table grants showing GRANTOR, GRANTEE and REM specific GRANTS. REM LIMITATIONS: User must have access to DBA_TAB_PRIVS REM INPUTS: Owner name REM OUTPUTS: Report of table grants REM REM HISTORY: REM Who: What: Date: REM Mike Ault Initial Creation 3/2/95 REM REM NOTES: Will not report grants to SYS or SYSTEM REM ACCEPT granted PROMPT ‘Enter Grantee: ‘ REM COLUMN GRANTEE FORMAT A18 HEADING "Grantee" COLUMN OWNER FORMAT A18 HEADING "Owner" COLUMN TABLE_NAME FORMAT A30 HEADING "Table" COLUMN GRANTOR FORMAT A18 HEADING "Grantor" COLUMN PRIVILEGE FORMAT A10 HEADING "Privilege" COLUMN GRANTABLE FORMAT A19 HEADING "With Grant Option?" REM BREAK ON owner SKIP 4 ON table_name SKIP 1 ON grantee ON grantor ON REPORT REM SET LINESIZE 130 PAGES 56 VERIFY OFF FEEDBACK OFF START title132 "TABLE GRANTS BY OWNER AND TABLE" SPOOL rep_out\&db\grants..lis REM SELECT owner, table_name, grantee, grantor, privilege, grantable FROM dba_tab_privs
WHITE PAPER COPYRIGHT © 2002 ROBO BOOKS. ALL RIGHTS RESERVED. PAGE 17

GUIDELINES

WHERE owner NOT IN ('SYS','SYSTEM') AND grantee = UPPER(&granted) ORDER BY owner, table_name, grantor, grantee; REM SPOOL OFF PAUSE Press enter to exit EXIT

WHITE PAPER COPYRIGHT © 2002 ROBO BOOKS. ALL RIGHTS RESERVED.

PAGE 18

Sign up to vote on this title
UsefulNot useful