Anda di halaman 1dari 17

PL/SQL Development Standard

Oracle PL/SQL
Development
Standard

Page 1 of 17
PL/SQL Development Standard

Contents

Scope of this document..................................................................................................3


Reason for coding standard............................................................................................4
Sections at which standards should apply......................................................................4
Naming Standard............................................................................................................6
Design guideline.............................................................................................................7
Coding guideline............................................................................................................8
Comments in code......................................................................................................8
Loop vs set operations................................................................................................8
Using tables for input and output...............................................................................9
Cursors......................................................................................................................10
Security.........................................................................................................................12
Error Handling..............................................................................................................13
Viewing Explain Plan...................................................................................................15
Implementing coding standard.....................................................................................16
Document control.........................................................................................................17

Page 2 of 17
PL/SQL Development Standard

Scope of this document


This document is the standard guideline for Oracle PL/SQL coding standard.

What this document will tell you:

• What standards to follow.


• How objects in database should be named
• What basic level of standard should be maintained in all codes written
in projects
• Some basic guidelines for writing code for better performance
• Some high level design guideline

What this document will NOT tell you:

• How to tune database (though some guidelines for better performance


is highlighted)
• How to debug your code
• How Oracle works
• Best practice for generic database design

Page 3 of 17
PL/SQL Development Standard

Reason for coding standard


In a project, where multiple developers work on different section of code at
different times, it becomes very difficult to maintain piece of code when
someone other than original developers have maintain (i.e. modify) the code.

Usually, everyone is unique in his/her thinking style. That behaviour is


reflected in his/her coding. As a consequence, another person might
approach same problem from a completely different perspective yet arriving at
same result.

So, this is necessary that everyone follow at least some sort of guidelines so
that collaboration among team members becomes easier over the time.

This document just provides some best practice guidelines. It should not be
considered as gospel as situations might dictate slight deviations from this
guideline.

However, adherence to this guideline will ensure an easier to read and


maintainable code for anyone working in the project in future.

Sections at which standards should apply

Development Area Includes


Spacing between statements; spacing between procedures and
Vertical spacing functions within package bodies.
Spacing between identifiers and operators; number of statements
Horizontal spacing per line; maximum line width.
Use of positional or named notation when calling stored PL/SQL
Procedural calls objects.
Type of comments to be used and the frequency, spacing,
Commenting positioning, and content of comments.
Contents of procedures and functions; organization of procedures
Code reuse/ Modularity and functions into packages.
Rules for naming identifiers; rules for naming stored PL/SQL objects
including tables, views, stored procedures/function, packages,
Identifiers indexes etc.

SQL statements Formatting rules for embedded SQL statements.

Performance Performance tips (particularly for embedded SQL statements).


Debugging/ Error A standard method of handling exceptions inside PL/SQL objects as
Handling well as inside other applications that call stored PL/SQL objects.
Rules for writing stored PL/SQL objects so that unit testing can be
Testability accomplished.
Development Rules determining what tools will be used for application
environment development and what processes must be followed by developers.

Page 4 of 17
PL/SQL Development Standard

Rules determining which keywords will be used in UPPER case,


Capitalization Mixed case, and lower case.
Conformance to Rules designating when it is allowable for code to not agree with the
standards coding standard.
Rules that designate whether the coding standards will be applied to
design documents and what type of documentation must exist for
Documentation particular routines.

Page 5 of 17
PL/SQL Development Standard

Naming Standard

Object type Prefix Example


Input parameter pi
Output parameter po
Cursor c cEpisodes
Package name Provide descriptive
names
Function name Provide descriptive Use a verb and then include that
name it is doing
Procedure name Provide descriptive UPDATE_ORDER_DETAIL
names
Table name Provide descriptive Decide whether you want to use
names singular or plural names eg.
CUSTOMER vs CUSTOMERS as
same convention must be
followed for all tables
View name Provide descriptive If possible, incorporate V_* or *_V
names to distinguish as view from name.
MV may be used for materialized
view prefix/suffix.
Primary key PK_ table name
Foreign key FK_ referenced Use appropriate abbreviation to
table name describe relationship if possible.
For large column names,
sometimes fully descriptive name
may not be possible.
Sequence sq_*
Trigger trg_*
Types typ_*
Check constrants chk_*
Variables inside Use short but descriptive names
procedure or depending on scope of variable.
function Global variables may be prefixed
with g_*.
Table alias A 3-character Unique table aliases names
standard table alias should be used across the
is recommended. project. A central documentation
(may be a separate table in
database) of all table aliases are
advised.
Index IDX_ttt_nnn Where ttt is table alias and nnn is
unique numbers to identify each
index. Instead of nnn key names
may be used.

Page 6 of 17
PL/SQL Development Standard

Design guideline

An Entity Relationship Diagram (ERD) must be made available as part of


design before PL/SQL coding starts.

ERD ensures better understanding of the relationship among various entities


(and tables in physical schema) and helps developers to write code which is
meaningful from business perspective.

It is advisable that you add comments against each column of tables to


provide a description of what the column is supposed to contain.

Example: execute this on SQL Plus


comment on column table_name.column_name is 'This is my
comment';

The comments can be viewed via common “desc” command in SQL Plus (or
any other client tool).

This provides virtually self-containing information on database. This becomes


very easy for testers to determine if a value is invalid (from business
perspective).

A flow chart (eg. Visio diagram or similar) must be provided for end to end
processing for which PL/SQL code needs to be developed. As a minimum, the
flow chart must show the names of input/output tables for each module.
Having a flow chart is very useful for pin pointing the exact place of failure in a
long batch job.

Following any change is design, all corresponding documents must be


updated to reflect up to date changes.

NOTE: A complete discussion of database design is beyond scope of this


document and so only the part relevant for PL/SQL coding is highlighted.

Page 7 of 17
PL/SQL Development Standard

Coding guideline

Comments in code

Use sufficient comments to describe what the section of code is doing. At the
beginning of a big procedure/function, clear description should be given and a
description of how the flow of program follows.

Depending on requirement, comment for each package/function/procedure


should include following information.

• What the function/procedure is suppose to do


• Name of developer
• Date of development
• Date of further amendments with reasons
• Explanation of parameters used with possible values
• Example of how the function/procedure can be called
• Where the output is written e.g. if procedure updates a table, name of
that table
• Whether running multiple times with same data will produce same or
different output. Some procedures are designed to modify information
in a rollover (running history) table. Running them multiple times out of
sequence may cause inconsistent output. In case where multiple run
produces inconsistent output, explanation must be given what to be
done before code can be run again to get consistent result.
• How the successful execution of function/procedure can be verified
• Names of input and output tables
• Prerequisites for the code i.e. what codes must be run before this code
can run
• Reusability – whether this module is used elsewhere
• Whether multiple instances of same procedure can run with different
parameters
• Name of requirement/functional/technical specification document has
been followed to develop the code

Loop vs set operations

Whenever possible use explicit column names with INSERT statement. This
will help to preserve code if columns are added or deleted from table later.

Whenever possible replace for loops with set statements. The later is more
efficient than the former.

Page 8 of 17
PL/SQL Development Standard

An example is given below,


FOR i IN 1..10000
LOOP
INSERT
INTO CALL_DATA VALUES (
sq_call_id.nextval
,(select phoneno from NUMBER_INFO SAMPLE(0.1) WHERE ROWNUM < 2)
,round(dbms_random.VALUE(1000000,9999999))
,TO_DATE(TRUNC(DBMS_RANDOM.VALUE(2453371, 2453371+5*365)), 'J')
,to_char(SYSDATE,'HH24:MI:SS')
,round(dbms_random.VALUE(1,30))
,null
);
COMMIT;
END LOOP;

Can be replaced by following piece of code


INSERT
INTO CALL_DATA
SELECT sq_call_id.nextval
,(select phoneno from NUMBER_INFO SAMPLE(0.1) WHERE ROWNUM < 2)
,round(dbms_random.VALUE(1000000,9999999))
,TO_DATE(TRUNC(DBMS_RANDOM.VALUE(2453371, 2453371+5*365)), 'J')
,to_char(SYSDATE,'HH24:MI:SS')
,round(dbms_random.VALUE(1,30))
,null
FROM DUAL
CONNECT BY ROWNUM <= 10000;
COMMIT;

Cursor should only be used when it is not at all possible to re-write the part of
the code using set operators.

Use anchored declaration for variables like %TYPE and %ROWTYPE


attributes whenever possible.

Using tables for input and output

All data must be read from and written into database tables. If some input files
come from OS files, a process should be there to upload these ASCII (or
whatever) files into database tables first.

Similarly, if output needs to be written to ASCII files (or similar), then output
data must be written to table(s) first and then a separate process should be
there to unload/extract data from output table(s) to OS file(s).

This approach ensures that entire processing is insulated from any OS


specific changes. This makes code easier to maintain and ensures portability
of code between different Operating Systems and servers.

Using intermediate or temporary tables

Page 9 of 17
PL/SQL Development Standard

Using writing to intermediate tables involves extra I/O operations and so it is


advised that if you do not use temporary tables for small operations.

However, sometimes using of temporary tables is recommended when:

• A large processing is performed which takes several hours to run. If


temporary tables are used to store intermediate result, then in case of
failure, process can be resumed from the save point.
• To avoid resource contention (locking etc.) issues when more than one
procedure are writing to same table, results can be stored in
intermediate table and be merged/appended to main table later.
• Temporary tables, if used, must be dropped or truncated when no
longer required.

Using pipeline function

Often a procedure writes its output to a table and after it finishes, another
procedure starts reading data from that table. If the 2nd process does not need
to wait for 1st process to finish, i.e. 2nd process can start its own processing as
soon as 1st job starts pumping its result, use of intermediate table can be
avoiding by judicial use of pipeline functions.

Cursors

Cursor should be opened in for loop to avoid explicit opening and closing of
cursor.

When cursor is used, use BULK COLLECT and FORALL to improve


performance. Use limit clause to avoid running out of memory.

Example:
create or replace procedure proc_test1 IS
CURSOR cTest IS SELECT * FROM test1 ORDER BY 1;
/* contains one number column and values from 1 to 10000 */
TYPE tTest IS TABLE OF cTest%ROWTYPE INDEX BY PLS_INTEGER;
ctTest tTest;
i NUMBER := 1;
BEGIN
OPEN cTest;
LOOP
FETCH cTest
BULK COLLECT
INTO ctTest
LIMIT 1000;

EXIT WHEN cTest%NOTFOUND OR cttest.COUNT =0;

FOR j IN 1..ctTest.COUNT
LOOP
-- do processing
--dbms_output.put_line(ctTest(j).abc);
NULL;
END LOOP;

Page 10 of 17
PL/SQL Development Standard

dbms_output.put_line('Reached here with i = ' || i);


i := i + 1;
END LOOP;
end proc_test1;

Here the limit clause specifies in single fetch to database, how many records
will be collected. It table test1 has 10,000 records; then the output line will be
printed from 1 to 10 for limit 1000.

Instead of writing this


FOR recIN emp_cur
LOOP
UPDATE employee SET salary = 10 WHERE employee_id= rec.employee_id;
END LOOP;

Write this
FORALL indx IN deptlist.FIRST..deptlist.LAST
UPDATE employee SET salary = 10 WHERE employee_id= deptlist(indx);

The later version is more efficient.

Page 11 of 17
PL/SQL Development Standard

Security
Database security should be designed from the beginning and not as an
afterthought!

All users should have their own log in id. Everyone in same group (eg.
developers, system testers etc.) should be assigned to specific roles. The
resource for each role should be allocated to avoid resource contention (i.e.
space issue, load on servers etc).

Logging of ad hoc SQL running against database should be enabled in cases


where performance problem is detected and/or to prevent querying sensitive
information by users.

All roles should be granted privileges only pertinent to the usage.

Access to production database should be restricted. However, there are


cases when developers need to access production database for problem
investigation and other purposes. All such access should be read only to
prevent any accidental modification of production data.

There should be a password policy. However, for development group, it need


not be too rigorous – i.e. developers do not need to be forced to change their
password often.

Encryption of data is advisable when business requirement demands it.

PL/SQL code can be wrapped to hide coding logic in case when application is
deployed to 3rd party server with intellectual property right remaining with
developers only.

Security should be set up in a way that it prevents unauthorised access yet


not too rigid to be impractical.

All changes to production database must be documented and released


properly. Adhoc changes to database data, structure etc. is not
recommended. Even if any such change is absolutely necessary, it must be
documented and care should be taken to revert back the changes quickly
without affecting normal database operation.

Personal log in details sharing should be discouraged.

Page 12 of 17
PL/SQL Development Standard

Error Handling

A generic error handling routine and table are recommended. A log table
instead of log file is recommended as writing to operating system files breaks
portability of application between platforms (like Windows and Unix).

Layout of a LOG_RECORD table can be like this.

LOG_ID NUMBER NOT NULL Primary key - use sequence to populate it


ERROR_NO VARCHAR2(100) Capture Oracle error number
ERROR_MESSAGE VARCHAR2(2000) Capture Oracle error message here
The name of function/procedure caused
PROGRAM_NAME VARCHAR2(200) it – should be specified as shown below
The description of function/procedure as
PROGRAM_DESC VARCHAR2(2000) specified in code – see below
USER_NAME VARCHAR2(100) Default to USER
WHEN_HAPPENED DATE Default to SYSDATE

Depending on requirement, other columns may be added in the table.

Example of a generic procedure to add records LOG_RECORD table is


shown below.

create or replace PROCEDURE INSERT_ERROR_LOG


(
piErrorNo in varchar2
, piErrorMessage in varchar2
, piProgramName in varchar2
, piErrorDescription in varchar2
) is
BEGIN
INSERT INTO LOG_RECORD VALUES (
SQ_LOG_ID.NEXTVAL
, piErrorNo
, piErrorMessage
, piProgramName
, piErrorDescription
, USER
, SYSDATE
);
COMMIT;
END;

Example of how you can call this code in your procedure is shown below.

CREATE OR REPLACE PROCEDURE TEST_ERROR IS


N NUMBER;

Page 13 of 17
PL/SQL Development Standard

PNAME VARCHAR2(100);
PDESC VARCHAR2(100);
BEGIN
PNAME := 'SELECT RECORD';
PDESC := 'STARTED SELECTING RECORD FROM TABLE';
INSERT_ERROR_LOG(SQLCODE, SQLERRM, PNAME, PDESC);

SELECT NUM INTO N FROM TEST WHERE NUM=1; /* It will


fail if where clause is removed */
DBMS_OUTPUT.PUT_LINE('SELECTING NUMBER...' || N);

PNAME := 'SELECT RECORD';


PDESC := 'FINISHED STEP 1';
INSERT_ERROR_LOG(SQLCODE, SQLERRM, PNAME, PDESC);

EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLERRM);
INSERT_ERROR_LOG(SQLCODE, SQLERRM, PNAME, PDESC);
END;

For large procedures (which has over 400 lines and takes over 15 minutes to
run as base line), it is advisable that developers take care that execution of
each stage of modules are reported in log table.

When a program fails, just reporting the error message in the log is not often
sufficient to debug the program efficiently.

A clue must be provided which provides some pointer to exactly where the
program failed.

That is why it is advisable that developers log start and end of each module of
execution so that it becomes easier to pin point exact place of failure.

It also has the added advantage of monitoring the progress of running of a


program which takes very long time (several hours for example).

There are some cases when error handling is not advisable! If a code is
executed manually directly on database (i.e. not from a front end application)
and there is no other error handling than simple WHEN OTHERS, then it
becomes very difficult to debug if the procedure/function fails. If error handling
is missing, Oracle just points out exactly on which line code failed – so makes
it faster to debug the code.

Page 14 of 17
PL/SQL Development Standard

Viewing Explain Plan

Following queries can be used to view explain plan of statements.

Generation of explain plan.

TRUNCATE TABLE PLAN_TABLE

EXPLAIN PLAN SET STATEMENT_ID = ‘identifier’ FOR


Your SQL statement

Viewing of explain plan.

SELECT LPAD(' ',4*(LEVEL-2)) || OPERATION || ' ' ||


OPTIONS || ' ' ||
OBJECT_NAME "EXECUTION_PLAN", IO_COST,
CPU_COST,TEMP_SPACE
,CARDINALITY, TIME
FROM PLAN_TABLE
START WITH ID = 0 CONNECT BY PRIOR ID = PARENT_ID

Any suitable name may be used as statement identifier provided that name is
not already existing in the PLAN_TABLE.

If PLAN_TABLE does not exist, it needs to be created by running utlxplan.sql.

Page 15 of 17
PL/SQL Development Standard

Implementing coding standard


As the coding standard is an extensive list, developers may miss out few
recommendations while coding.

So, it is recommended that at early testing phase (ideally during unit testing),
the code be peer reviewed so that all omissions to standard are pointed out
and corrected.

If any standard is omitted, developers must be able to provide an informal


explanation of why it was done in that way.

Rigorous implementation may seem laborious in short term, but it offers


immense benefit in maintainability of code in longer term.

Coding standard is immensely helpful when code is maintained by support


team members who were not originally involved in the development stage.

Page 16 of 17
PL/SQL Development Standard

Document control
Version Date Author Comment
1.0 Oct 2009 S Basak

Page 17 of 17