i2 PLSQL Coding Standards

download i2 PLSQL Coding Standards

of 23

Transcript of i2 PLSQL Coding Standards

  • 7/30/2019 i2 PLSQL Coding Standards

    1/23

    PL/SQL Coding Standard 1

    PL/SQLCODING STANDARDS

    {REVISION 1.0 / 28-FEB-2005}

    2001 i2 Technologies, PROPRIETARY and CONFIDENTIAL 28/02/2005

  • 7/30/2019 i2 PLSQL Coding Standards

    2/23

    PL/SQL Coding Standard 2

    TABLE OF CONTENTS

    2001 i2 Technologies, PROPRIETARY and CONFIDENTIAL 28/02/2005

  • 7/30/2019 i2 PLSQL Coding Standards

    3/23

    PL/SQL Coding Standard 3

    Purpose:

    PL/SQL code must be maintainable and professional. This means that it must beconsistent and therefore must abide by certain standards. The standards will ensure thatour product will be useful long after the current people building and maintaining it arearound.

    Introduction:

    This documents contains two parts:Part A: PL/SQL Coding StandardsPart B: PL/SQL Structure

    A. PL/SQL Standards

    General1. All PL/SQL code must be well documented. We must write code that is

    maintainable by others. Our motto is, "Document like you are trying toimpress your favorite programming professor."

    2. It is important to be consistent throughout an application as much as is

    possible given the nature of team development. This means carrying styleand other conventions such as naming within an application, not just withinone file.

    A.1. Coding Standards

    1. Encapsulation of related functionality is key to making our software maintainable

    and upgradeable. Try to bundle your code into packages whenever possible. Thiswill make upgrading, bug fixing, customizing, and many other things, a possibility.

    2. When creating functions or procedures, use the following template. It

    demonstrates most of the guidelines set forth in this document that correspond tofunctions and procedures:

    CREATE OR REPLACE PROCEDURE/FUNCTION (

    IN/OUT/INOUT ,

    IN/OUT/INOUT ,

    ...

    IN/OUT/INOUT

    )[RETURN ]

    IS

    ...

    BEGIN

    ...

    END;

    2001 i2 Technologies, PROPRIETARY and CONFIDENTIAL 28/02/2005

  • 7/30/2019 i2 PLSQL Coding Standards

    4/23

    PL/SQL Coding Standard 4

    /

    3. All Key words should be in uppercase.

    Ex: BEGIN, END, SELECT, INSERT, UPDATE, DELETE , CREATE ORREPLACE PROCEDURE, IN, OUT, INOUT IF, END IF etc.

    4. Naming convention of Procedure and functions should be P_procedurename andF_funtionname

    Ex: P_sitemaster_upd, F_worklists

    5. All local variables defined in procedure should be l_variablename(lowercase)

    Ex: l_itemname, l_locationname etc

    6. All input and output parameters to procedure should be

    I_inputparametername(lowercase) and o_outputparametername.

    Ex: i_planid, o_cumulativeyield etc

    7.Code should be proper aligned. Left alignment for BEGIN EXCEPTION and ENDblock. Right alignment for SQL statement.

    Ex: BEGIN

    SELECT plan_id,eff_start_date,eff_end_date

    INTO l_plan_id,l_eff_start_date,l_eff_end_date

    FROM plan_master;

    EXCEPTION WHEN NO_DATA_FOUND THEN

    RAISE_APPLICATION_ERROR(-errcode,errormessage);

    END;

    8. There should be proper comments for each block of code.

    9. Exception should handle for each sql statement.

    Ex: BEGIN

    SELECT plan_id,eff_start_date,eff_end_date

    INTO l_plan_id,l_eff_start_date,l_eff_end_date

    FROM plan_master;

    EXCEPTION WHEN NO_DATA_FOUND THEN

    RAISE_APPLICATION_ERROR(-errcode,errormessage);END;

    10.Cursor name should be c_cursorname(lower case)

    Ex: c_mst_location

    11. Reference cursor name should be c_RefCursors.

    Ex: c_RefCursors

    2001 i2 Technologies, PROPRIETARY and CONFIDENTIAL 28/02/2005

  • 7/30/2019 i2 PLSQL Coding Standards

    5/23

    PL/SQL Coding Standard 5

    Ex: -- Ref Cursor Declaration Part

    TYPE c_RefCursors IS REF CURSOR;

    c_udp_engine c_RefCursors;

    c_null_calendars c_RefCursors;

    12. Cursor record set name should be cursorname_rec(lowercase)

    Ex: c_mst_location_rec

    Ex: FOR c_mst_location_rec IN c_mst_location

    LOOP

    BEGIN

    EXCEPTION

    END;

    END LOOP;

    13.Naming convention of cursor parameter should be p_cur_paramname

    Ex: p_cur_planid

    CURSOR c_udp_engine(p_cur_planid out_release_location.plan_id%TYPE)IS SELECT DISTINCT enginename, mp_engineid FROM udt_enginenmasterWHERE mp_planid=l_planid;

    14.Use %TYPE and %ROWTYPE where ever possible.

    15.Use standard error handling process to log all oracle errors.

    16.User exception should be declared as e_exceptioname.

    17. Always put WHEN OTHERS exception at end of each code block.

    18.Use DBMS_OUTPUT.PUT_LINE ('sqltext- '||sqltext); for debug the code.

    A.2. Coding Style

    Some general style guidelines like alignment, spaces to be followed for the purpose ofconsistency across applications.

    1. Standard indentation is four spaces. Our PL/SQL code is not only viewable in the

    SQL files but also through our SQL and PL/SQL browsers. This means that weshould try to make it as consistent as possible to all source code readers.

    2. Lowercase everything (table name, field name, local variable name, parameters

    name etc.) with the exception of %TYPE, %ROWTYPE and all KEY WORDS.

    A.3. Constraint Naming Standards

    A constraint naming standard is important for one primary reason: The SYS_* nameOracle assigns to unnamed constraints is not very understandable. By correctly naming all

    2001 i2 Technologies, PROPRIETARY and CONFIDENTIAL 28/02/2005

  • 7/30/2019 i2 PLSQL Coding Standards

    6/23

    PL/SQL Coding Standard 6

    constraints, we can quickly associate a particular constraint with our data model. Thisgives us two real advantages:

    We can quickly identify and fix any errors

    We can reliably modify or drop constraints

    Why do we need a naming convention? Oracle limits names, in general, to 30 characters,which is hardly enough for a human-readable constraint name.

    A.3.1. Abbreviations

    We propose the following naming convention for all constraints, with the followingabbreviations taken from the Oracle documentation. Note that we shortened all of theconstraint abbreviations to two characters to save room.

    Constraint type Abbreviation

    references (foreign key) Fk

    unique Un

    primary key Pk

    check ck

    Not null nn

    A.3.2. Format of Constraint Name

    __In reality, this won't be possible because of the character limitation on names insideOracle. When the name is too long, we will follow these steps in order:

    Abbreviate the table name with the table's initials (for example, users -> u andusers_contact -> uc).

    Truncate the column name until it fits.

    create table example_topics (topic_id integer

    constraint example_topics_topic_id_pk primary key);

    create table constraint_naming_example (example_id integer constraint cne_example_id_pk primary key,one_line_description varchar(100)

    constraint cne_one_line_desc_nn not null,

    2001 i2 Technologies, PROPRIETARY and CONFIDENTIAL 28/02/2005

  • 7/30/2019 i2 PLSQL Coding Standards

    7/23

    PL/SQL Coding Standard 7

    body clob,up_to_date_p char(1) default('t')

    constraint cne_up_to_date_p_check check(up_to_date_p in ('t','f')),topic_id

    constraint cne_topic_id_nn not nullconstraint cne_topic_id_fk references example_topics,

    -- Define table level constraintconstraint cne_example_id_one_line_unqunique(example_id, one_line_description)

    );

    Example B-1. Example of Constraint Name

    Note

    If you have to abbreviate the table name for one of the constraints, abbreviate it forall the constraints.If you are defining a multicolumn constraint, try to truncate the two column namesevenly.

    A.3.3. Namingprimary keysNaming primary keys might not have any obvious advantages. However, in Example B-2, theprimary key helps make the SQL query clearer.

    SQL> set autotrace traceonly explain;

    SQL> select * from constraint_naming_example, example_topics

    where constraint_naming_example.topic_id = example_topics.topic_id;

    Execution Plan----------------------------------------------------------0 SELECT STATEMENT Optimizer=CHOOSE1 0 NESTED LOOPS2 1 TABLE ACCESS (FULL) OF 'CONSTRAINT_NAMING_EXAMPLE'3 1 INDEX (UNIQUE SCAN) OF 'EXAMPLE_TOPICS_TOPIC_ID_PK' (UNIQUE)

    Example B-2. Primary Key Naming

    Being able to see EXAMPLE_TOPICS_TOPIC_ID_PK in the trace helps us to knowexactly which table Oracle is querying.

    If we had not named the constraints, the execution plan would look like:

    Execution Plan----------------------------------------------------------0 SELECT STATEMENT Optimizer=CHOOSE1 0 NESTED LOOPS2 1 TABLE ACCESS (FULL) OF 'CONSTRAINT_NAMING_EXAMPLE'3 1 INDEX (UNIQUE SCAN) OF 'SYS_C00140971' (UNIQUE)

    2001 i2 Technologies, PROPRIETARY and CONFIDENTIAL 28/02/2005

    http://www.redhat.com/docs/manuals/waf/rhea-dg-waf-en-6.0/s1-sqlstan-constraint-naming.html#EX-SQL-STDS-PRIMARY-KEY-NAMINGhttp://www.redhat.com/docs/manuals/waf/rhea-dg-waf-en-6.0/s1-sqlstan-constraint-naming.html#EX-SQL-STDS-PRIMARY-KEY-NAMING
  • 7/30/2019 i2 PLSQL Coding Standards

    8/23

    PL/SQL Coding Standard 8

    The SYS_C00140971 by itself provides no information as to which index is being used inthis query, and more importantly, the name of this constraint will vary from database todatabase.Mark Lindsey () provided another good reason to name primary keysand unique constraints. Oracle creates an index for every primary key and uniqueconstraint with the same name as the constraint. It is an unfortunate DBA who has towrestle with storage management of tens of mysteriously-named indexes.

    A.3.4. Namingnot nullConstraintsisOptional.

    Red Hat Applications developers are undecided on whether or not to name not nullconstraints. If you want to name them, please do so and follow the above namingstandard. Currently, naming not null constraints is nota requirement of WAF.

    Note

    Naming the not null constraints does not help immediately in error debugging (for

    example the error will say something like Cannot insert null value into column). Wedo recommend naming not null constraints to be consistent in our naming of all

    constraints.

    A.3.5. Upgrade Scripts

    Data model upgrade scripts are a crucial part of database-based applications. Standardshelp to ensure that upgrade scripts behave correctly and consistently. This helps save time

    in development, maintenance, and support.

    Tip

    An upgrade script should be written anytime that a change is made to a component'ssql creation script that results in a different schema and/or data set. The newupgrade script should be written so that, when applied to the previous creation script,

    it results in the same schema and data set.

    Every component should have exactly zero or one upgrade script per release persupported database. However, an upgrade script may source other files.

    Upgrade scripts go in an upgrade/ directory below the directory containing thecorresponding creation script. The name of the file should be --.sql.

    Example:

    Cms/sql/oracle-se/upgrade/cms-4.6.4-4.6.5.sql

    Extending this process farther, there should be a single upgrade script for all of WAF perversion. This upgrade script lives in kernel/sql/oracle-se/upgrade and is called core-platform- -.sql.

    2001 i2 Technologies, PROPRIETARY and CONFIDENTIAL 28/02/2005

    mailto:[email protected]:[email protected]
  • 7/30/2019 i2 PLSQL Coding Standards

    9/23

    PL/SQL Coding Standard 9

    Similar to core-platform-create.sql, this script will not have its own SQL commands, butwill simply source other files. Updating this script is the responsibility of each

    component developer.

    A.4. Sample Procedure (Contains Cursor, Dynamic Cursor)

    CREATE OR REPLACE PROCEDURE P_upd_rwc_ods_sitemaster(i_workflow_id IN

    INTEGER,i_odsschema IN VARCHAR2) AS

    -- In order to use workflow list function

    TYPE c_RefCursors IS REF CURSOR;

    c_udp_engine c_RefCursors;

    c_null_calendars c_RefCursors;

    --

    -- Local variable declaration part

    --

    l_workflowlist VARCHAR2(1000) := '';

    l_sqltext VARCHAR2(300);

    l_enginename varchar2(40);

    l_mp_engineid varchar2(40);

    l_release_calname VARCHAR2(200);

    l_planname VARCHAR2(40);

    l_attributevalue VARCHAR2(40);

    l_effstartdate DATE;

    l_effenddate DATE;

    l_startdate DATE := sysdate;

    l_jobname Varchar2(40) := 'Release Calendar Updation';

    l_standardflow INTEGER := 1;

    -- Exceptions

    2001 i2 Technologies, PROPRIETARY and CONFIDENTIAL 28/02/2005

  • 7/30/2019 i2 PLSQL Coding Standards

    10/23

    PL/SQL Coding Standard 10

    e_workflow_id_error Exception;

    -- Error Statements And Codes

    e_workflow_id VARCHAR2(1000) := 'Erroneous Workflow Identifier , Please

    Check the Input Id : ';

    e_update_error VARCHAR2(1000) := 'No Update Value Clause , Invalidquery .. exiting';

    e_lookup_error VARCHAR2(1000) := 'No Destination Look Up Field Specified ,

    Please check Input Parameters';

    --

    -- cursor declaration part

    --

    CURSOR c_mst_location IS

    SELECT DISTINCT plan_id, location_id, ud_release_time_monday,

    ud_release_time_tuesday, ud_release_time_wednesday,

    ud_release_time_Thursday, ud_release_time_friday

    FROM out_location_release@MDM

    WHERE location_id IS NOT NULL

    AND sys_ent_state='ACTIVE';

    BEGIN

    -- Check the workflows For which the update needs to run - Applicable only in

    case

    l_workflowlist := NVL(F_workflowlist(i_workflow_id),'Error');

    -- If the Workflow Id was Incorrect Raise An error

    IF l_workflowlist = 'Error' THEN

    RAISE e_workflow_id_Error;

    END IF;

    -- Set All engines valid for Workflow to Null as part of deletion

    -- OPEN dynamic Cursor c_null_calendars

    OPEN c_null_calendars FOR

    'SELECT DISTINCT enginename FROM UDT_ENGINEMASTER WHERE workflowid in ('

    || l_workflowlist || ')';

    LOOP

    FETCH c_null_calendars INTO l_enginename;

    BEGIN

    L_sqltext:='UPDATE ' || i_odsschema || '.v_sitemaster SET

    UDF_RELEASE_CALENDAR_'|| l_enginename ||'= NULL';

    EXECUTE IMMEDIATE l_sqltext;

    2001 i2 Technologies, PROPRIETARY and CONFIDENTIAL 28/02/2005

  • 7/30/2019 i2 PLSQL Coding Standards

    11/23

    PL/SQL Coding Standard 11

    EXCEPTION

    WHEN OTHERS THEN

    LOG_STANDARD_ERROR('v_sitemaster','SiteMaster Updation Failed '||

    sqlerrm,l_enginename,l_jobname,1,'S3',l_startdate);

    END;

    l_enginename:=NULL;

    EXIT WHEN c_null_calendars%NOTFOUND;

    END LOOP;

    COMMIT;

    l_enginename:=NULL;

    l_planname:=NULL;

    FOR c_mst_location_rec IN c_mst_location

    LOOP

    -- OPEN dynamic Cursor c_udp_engine

    OPEN c_udp_engine FOR

    'SELECT DISTINCT enginename,mp_engineid,mp_planid FROM udt_enginemaster

    WHERE mp_planid='||''''|| c_mst_location_rec.plan_id ||''''||' and workflowid

    in (' || l_workflowlist || ')';

    LOOP

    FETCH c_udp_engine INTO l_enginename,l_mp_engineid,l_planname;

    BEGINEXECUTE IMMEDIATE 'SELECT a.plan_id,b.currentdate,b.effenddate FROM

    out_planmaster@MDM a,'|| i_odsschema ||'.planmaster b where a.plan_id=''' ||

    l_planname ||''' AND a.plan_id=b.planid ' INTO

    l_planname,l_effstartdate,l_effenddate;

    EXCEPTION

    WHEN OTHERS THEN

    LOG_STANDARD_ERROR('OUT_PLANMASTER AND PLANMASTER','Plan Name retrival

    failed'|| sqlerrm, c_mst_location_rec.plan_id, l_jobname, 1, 'S3',

    l_startdate);

    END;

    l_release_calname:='RWC'||'.'||c_mst_location_rec.location_id||'.'||

    l_planname;

    BEGIN

    l_sqltext:= 'UPDATE '||i_odsschema||'.V_SITEMASTER SET

    UDF_RELEASE_CALENDAR_'||l_enginename||' ='''||l_release_calname||''' WHERE

    SITEID='''|| c_mst_location_rec.location_id||'''';

    2001 i2 Technologies, PROPRIETARY and CONFIDENTIAL 28/02/2005

  • 7/30/2019 i2 PLSQL Coding Standards

    12/23

    PL/SQL Coding Standard 12

    DBMS_OUTPUT.PUT_LINE ('l_sqltext- '||l_sqltext);

    EXECUTE IMMEDIATE sqltext;

    EXCEPTION

    WHEN OTHERS THEN

    LOG_STANDARD_ERROR('SITEMASTER','SITEMASTER RWC updation failed'||

    sqlerrm,l_release_calname,l_jobname,1,'S3',l_startdate);

    END;

    COMMIT;

    EXIT WHEN c_udp_engine%NOTFOUND;

    END LOOP;

    l_enginename:=NULL;

    COMMIT;

    END LOOP;

    EXCEPTION

    WHEN e_workflow_id_Error THEN

    RAISE_APPLICATION_ERROR(-20001,'Unknown Error Occurred : ' || sqlerrm);

    ROLLBACK;

    WHEN OTHERS THEN

    ROLLBACK;

    RAISE_APPLICATION_ERROR(-20001,'Unknown Error Occurred : ' || sqlerrm);

    END;

    /

    B.PL/SQL Structure

    This contains details of PL/SQL structures and definitions.

    B.1 Headers

    B.1.1 Create Command in PL/SQLThe first part of any stored procedure, package, package body, or function in PL/SQL isthe CREATE command. The CREATE command should use the OR REPLACE clause toensure that new updates write over old code. You should place the variable declarationsin the CREATE command on separate lines for readability, as well as the AS keyword. AllIN only variables should come first, followed by the IN OUT or OUT variables. Foranonymous blocks, the CREATE command is replaced with the DECLARE keyword

    2001 i2 Technologies, PROPRIETARY and CONFIDENTIAL 28/02/2005

  • 7/30/2019 i2 PLSQL Coding Standards

    13/23

    PL/SQL Coding Standard 13

    B.1.2 Special Case: CREATE PACKAGE Commands

    A special case is the CREATE PACKAGE command. The CREATE PACKAGE commandactually defines the package specification, or application programming interface (API), ofa PL/SQL package of functions and procedures. A good example of a useable codeguideline for this command structure is shown in the DBMS*.SQL procedures provided byOracle Corp. Listing 3shows an example of the CREATE PACKAGE format (note that all

    of the package header is shown -- only enough to illustrate the format is shown).Notice that each PROCEDURE declaration is properly indented and a blank line isinserted between each declaration section. Also note the use of comments to provideonline documentation. Other possible declaration statements are FUNCTION, CURSOR,and EXCEPTION. Before the first PROCEDURE declaration are the global variabledeclarations. Global variables in the package specification can be used by any program,including those defined later in the package body. Global constants can also be declaredin this fashion.Listing 4shows other declarations for the CREATE PACKAGE command. Note the use ofthe RETURN clause on the FUNCTION declaration in Listing 4; the EXCEPTIONkeyword follows the name of the exception. Generally you should list procedures andfunctions in order of dependency, followed by cursors, variables, and exceptions. Usecomments freely to ensure that future users will be able to understand how each item

    should be used.For the package body, the command is:CREATE OR REPLACE PACKAGE BODY name ASfollowed by the code for the various package objects. The object code is identical to thecode that you would use in a CREATE OR REPLACE script, except that the CREATE ORREPLACE command is not needed for individual package objects. Remember that thepublic package object definitions must exactly match their declarations in the packagespecification, and the developer can add additional private package objects.

    B.2 Cursor Declaration in PL/SQL

    Following the header in PL/SQL will be the DECLARE for anonymous blocks or theCREATE OR REPLACE command, the in/out variable declaration, and then the cursordeclaration. Listing 5 shows an example cursor definition. The format shown in Listing 5is easy to read and allows a quick scan of required inputs or outputs.

    B.2.1 Variable Definitions in PL/SQL

    After the cursor definitions in PL/SQL should come the variable definitions -- ROWTYPE,TYPE, TABLE, and RECORD -- followed by local definition variables. These definitionsshould be tab-separated for readability. Listing 6 shows some example variabledeclarations. On some platforms, tab separations may result in readability problems if thecode is transferred to a different platform with different editor characteristics. If you will beusing the code on multiple machines or under differing editors, use a fixed-width font andspace separation. Comments should also be added to the code to ensure understandingof the use of the variables.

    B.3 Body Definitions in PL/SQLThe body of the PL/SQL procedure consists of several possible constructs such as loops,selects, begin-end blocks, and exceptions. These constructs should use tab-indenting (ifthey are small) or space-indenting (if they are large) to promote readability. Clauses inSELECT, INSERT, or UPDATE commands should be placed on separate lines andslightly indented under the parent command. All loop contents should be indented insideof each loop construct. All block contents should be indented inside each BEGIN-ENDpair.

    2001 i2 Technologies, PROPRIETARY and CONFIDENTIAL 28/02/2005

    http://www.oreview.com/#listing3http://www.oreview.com/#listing3http://www.oreview.com/#listing4http://www.oreview.com/#listing4http://www.oreview.com/#listing5http://www.oreview.com/#listing6http://www.oreview.com/#listing3http://www.oreview.com/#listing4http://www.oreview.com/#listing5http://www.oreview.com/#listing6
  • 7/30/2019 i2 PLSQL Coding Standards

    14/23

    PL/SQL Coding Standard 14

    Procedure lengths should be set at a predetermined standard based on ensuring thatdevelopers modularize their code. Procedures much longer than 100 lines become hardto read. This is accomplished through compartmentalization of code into subproceduresand functions and through the use of cursors for multiple SELECT statements. A line ofcode is considered to be a single command, so even though a large SELECT, INSERT, orUPDATE type command spans several physical lines, it is only one line of code.

    For example, if the procedure in Listing 7 has been built in your schema or if you haveexecute privilege on it, the procedure can be called from other procedures to provideinsert processing into i_temp: By using subprocedures you can reduce the spacerequirements in your procedures. There should be comments added into the processingbody to show functions and explain special processing (if needed). See Listing 8 on theOReviewWeb site (www.oreview.com) for a code fragment using these techniques.

    B.4 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 theEXCEPTION keyword and should follow the other indention rules. Listing 9 shows anexample of an exception statement.

    So far I have covered all of the pieces and their formats for a PL/SQL script. Let's look ata complete example.Listing 10shows how all of these elements combine to make a veryeasily readable and thus maintainable piece of PL/SQL code.

    Each shop should determine its desired PL/SQL coding style and publish a codeguidebook for use by its developers. The code guidebook should delineate capitalizationrules, indentation rules, and naming standards. Developing without a code guidebook canlead to results that vary wildly from one developer to another in terms of readability andmaintainability. Poorly formatted code will increase maintenance time and thus

    maintenance cost.

    Listing 1. Example format for a PL/SQL header or footer.- -- - Title: (name of script)- - Used by Application: (application the- - procedure/function/package 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.)

    2001 i2 Technologies, PROPRIETARY and CONFIDENTIAL 28/02/2005

    http://www.oreview.com/#listing7http://www.oreview.com/#listing8http://www.oreview.com/#listing9http://www.oreview.com/#listing10http://www.oreview.com/#listing10http://www.oreview.com/#listing10http://www.oreview.com/#listing7http://www.oreview.com/#listing8http://www.oreview.com/#listing9http://www.oreview.com/#listing10
  • 7/30/2019 i2 PLSQL Coding Standards

    15/23

    PL/SQL Coding Standard 15

    Listing 2. Example format for a CREATE or DECLARE

    command.*Header*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 - -

    DECLAREvariable, constant, cursor or sub-program declarations

    Listing 3. Example of the CREATE PACKAGE command.

    *Header*CREATE OR REPLACE PACKAGE dbms_refresh IS-- dbms_refresh is the interface for administering refresh groups.-- PARAMETERS:-- NAME is of the form 'foo' or 'user.foo' or 'USER'.'FOO'.-- The logged-in user is used as a default.-- LIST is a comma-separated list of objects to be refreshed, such as-- 'foo, scott.bar ,'SCOTT'.'BLUE'. The default user is the owner-- of the refresh group.-- TAB is a PL/SQL table of objects to be refreshed, starting with 1-- and filling every number until an entry is NULL, with every entry-- formatted the same way as NAME. The default user is the owner-- of the refresh group.-- NEXT_DATE is the date for the refresh group to first be refreshed.-- See dbmsjobq.sql. If there is no current job, the default interval-- will be 'null' and the job will delete itself after refreshing the-- group at NEXT_DATE.-- INTERVAL is used to determine the next NEXT_DATE. See dbmsjobq.sql.-- If there is no current job, NEXT_DATE will default to null and the-- job will not run until you manually set NEXT_DATE to something else-- or manually refresh the group.-- IMPLICIT_DESTROY means to delete the refresh group when the last item-- is subtracted from it. The value is stored with the group definition.-- Empty groups can be created with IMPLICIT_DESTROY set.aaspriv BINARY_INTEGER;-- Privilege number for ALTER ANY SNAPSHOT

    PROCEDURE subtract( name IN VARCHAR2, list IN VARCHAR2, lax INBOOLEAN DEFAULT FALSE );PROCEDURE subtract( name IN VARCHAR2, tab IN dbms_utility.uncl_array, lax

    IN BOOLEAN DEFAULT FALSE );-- SUBTRACT some refreshable objects from a refresh group.PROCEDURE user_export_child( myowner IN VARCHAR2, myname IN VARCHAR2,

    mytype IN VARCHAR2, mycall IN OUT VARCHAR2);

    2001 i2 Technologies, PROPRIETARY and CONFIDENTIAL 28/02/2005

  • 7/30/2019 i2 PLSQL Coding Standards

    16/23

    PL/SQL Coding Standard 16

    -- Produce the text of a call for recreating the given group itemEND dbms_refresh;

    Listing 4. Other possible declarations with CREATE PACKAGE.

    CREATE PACKAGE admin.employee_packageAS

    -- employee package contains objects for the HR applicationPROCEDURE new_emp( ename IN VARCHAR2, position IN VARCHAR2,

    supervisor IN NUMBER, category IN NUMBER, hiredate IN DATE, emp_no OUTNUMBER);-- The procedure new_emp adds a new employee and returns their emp_no value.

    PROCEDURE fire_them( emp_no IN NUMBER, reason IN VARCHAR2,term_date IN OUT DATE);-- The procedure fire_them removes an employee and returns their termination date

    PROCEDURE new_dept( emp_no IN NUMBER, dept IN VARCHAR2,new_dept IN VARCHAR2, date_of_change IN OUT DATE);-- The procedure new_dept changes an employees department and returns the dateof change.

    FUNCTION get_status ( emp_no IN NUMBER)

    RETURN VARCHAR2;-- The function get_status takes in the employee number and returns their status.

    CURSOR c_get_emp ( emp_num NUMBER) ISSELECT ename, dept, status, hiredate, supervisor

    FROM empWHERE emp_no=emp_num;

    -- The CURSOR c_get_emp is a general purpose cursor that returns all columns for a-- specified employee number entry.

    bad_category EXCEPTION;bad_date EXCEPTION;

    END employee_package;

    Listing 5. Example cursor declaration format.

    *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)

    (parameter list)IS

    SELECT(list of columns)

    FROM(list of tablesWHERE(list of clauses)

    2001 i2 Technologies, PROPRIETARY and CONFIDENTIAL 28/02/2005

  • 7/30/2019 i2 PLSQL Coding Standards

    17/23

    PL/SQL Coding Standard 17

    ORDER BY(list of columns)FOR UPDATE OF(Other clauses)

    (list of tables, columns, etc.) ;Other clauses should be indented in a similar manner.Remember, the objective is to make the code easily readable.For example:CURSOR c_cons_cursor IS

    SELECT owner, constraint_name,decode(constraint_type,'C','CK_','V','DF_'), table_name,

    search_condition, r_owner, r_constraint_name, delete_ruleFROM user_constraints

    WHERE owner NOT IN ('SYS','SYSTEM')AND constraint_type IN ('C','V')

    ORDER BY owner, constraint_type ;

    Listing 6. Example variable declarations.

    *Header**Create or Declare**Cursors*- - Table Definitions- -

    TYPE numtab IS TABLE OF NUMBERINDEX 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;

    2001 i2 Technologies, PROPRIETARY and CONFIDENTIAL 28/02/2005

  • 7/30/2019 i2 PLSQL Coding Standards

    18/23

    PL/SQL Coding Standard 18

    cons_name user_constraints.constraint_name%TYPE;- -- - Local Variable Definitions- -

    cons_type varchar2(11);all_columns varchar2(2000);counter integer:=0;cons_nbr integer;

    Listing 7. Example of a sub-procedure.

    CREATE OR REPLACE PROCEDURE write_ind(p_line INTEGER,

    p_owner varchar2,p_name VARCHAR2,p_string VARCHAR2)

    ISBEGIN

    INSERT INTO i_temp ( lineno, id_owner, id_name, text)VALUES ( p_line, p_owner, p_name, p_string);

    END;

    Listing 8. Example code fragment using indentation, commenting andcapitalization rules.

    *Header**Create or Declare**Cursors**Declarations*- -- - Create a command set to rebuild a CREATE DATABASE command- -BEGINdb_lineno:=db_lineno+1;SELECT 'CREATE DATABASE ' | | value into db_stringFROM v$parameter

    WHERE name='db_name';write_ind(db_lineno,db_string);

  • 7/30/2019 i2 PLSQL Coding Standards

    19/23

    PL/SQL Coding Standard 19

    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_stringFROM dual;write_ind(db_lineno,db_string);COMMIT;- -- - Get redo log thread information- -IF thread_cursor%ISOPENTHEN

    CLOSE thread_cursor;OPEN thread_cursor;

    ELSEOPEN 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

    THENCLOSE mem_cursor;OPEN mem_cursor(grp);

    ELSEOPEN 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_linenoTHEN

    db_string:=''''| | grp_member | |'''';write_ind(db_lineno,db_string);db_lineno:=db_lineno+1;

    ELSEdb_string:=','| |'''| | grp_member| |''';write_ind(db_lineno,db_string);db_lineno:=db_lineno+1;

    2001 i2 Technologies, PROPRIETARY and CONFIDENTIAL 28/02/2005

  • 7/30/2019 i2 PLSQL Coding Standards

    20/23

    PL/SQL Coding Standard 20

    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_stringFROM dual;write_ind(db_lineno,db_string);COMMIT;- -- - Get datafile information for the SYSTEM tablespace- -IF dbf_cursor%ISOPEN

    THENCLOSE dbf_cursor;OPEN dbf_cursor;

    ELSEOPEN dbf_cursor;

    END IF;begin_count:=db_lineno;LOOP

    FETCH dbf_cursor INTO filename, sz;EXIT WHEN dbf_cursor%NOTFOUND;IF begin_count=db_linenoTHEN

    db_string:='DATAFILE '| |''''| | filename| |''''| |' SIZE '| |sz| |' REUSE';

    ELSEdb_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 wemust decode- -SELECT

    decode(value,'TRUE','ARCHIVELOG','FALSE','NOARCHIVELOG')INTO db_string

    FROM v$parameterWHERE name='log_archive_start';db_lineno:=db_lineno+1;write_ind(db_lineno,db_string);SELECT

    2001 i2 Technologies, PROPRIETARY and CONFIDENTIAL 28/02/2005

  • 7/30/2019 i2 PLSQL Coding Standards

    21/23

    PL/SQL Coding Standard 21

    ';' INTO db_stringFROM dual;db_lineno:=db_lineno+1;write_ind(db_lineno,db_string);

    CLOSE dbf_cursor;CLOSE mem_cursor;CLOSE thread_cursor;COMMIT;END;

    Listing 9. Example of the format for an EXCEPTION statement.

    *Header**Create or Declare*

    *Cursors**Declarations**Body*EXCEPTION

    WHEN NO_DATA_FOUND THENINSERT INTO

    dba_tempVALUES (

    stat_name,0);COMMIT;WHEN ZERO_DIVIDE THENINSERT INTO

    dba_temp

    VALUES (stat_name,0);

    COMMIT;

    Listing 10. Full-length code example.

    - -- - Title: AddRmaNote- - Used by Application: RMA GUI- - Purpose: Add RMA notes

    - - Limitations: None- -- - Inputs: eventid, actseqnbr, user, notes- - Outputs: status: 1 No note added, 0 note added- -- - History:

    2001 i2 Technologies, PROPRIETARY and CONFIDENTIAL 28/02/2005

  • 7/30/2019 i2 PLSQL Coding Standards

    22/23

    PL/SQL Coding Standard 22

    - - Who: What: Date:- - Mike Ault Added Header 12/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- -

    BEGINhv_status := 0;leid := 0;BEGIN- -- - Get the foreign key value of the leid from the

    - - indiv table for this user- -

    SELECT fk_leleid INTO leidFROM indivWHERE cuidnbr = hv_user ;EXCEPTION WHEN OTHERS THEN

    - -- - If no entry then user doesn't have the leid value- - required and no note will be added to RMA return a 1- - status- -

    hv_status := 1;

    END;- -- - Get SYSDATE, note, an error of 1427 may indicate- - multiple rows in dual- -

    SELECT sysdate INTO date1 FROM dual;- -

    2001 i2 Technologies, PROPRIETARY and CONFIDENTIAL 28/02/2005

  • 7/30/2019 i2 PLSQL Coding Standards

    23/23

    PL/SQL Coding Standard 23

    - - A leid number greater than zero indicates we need to- - add to the activity remark table (add an RMA note)- -

    IF ( leid > 0 ) THEN

    INSERT INTO actvy_rmk ( actvyrmkdt, actvyrmktxt,fk_actfk_eventevnt,

    fk_actactseqnbr, fk_indivfk_leleid )VALUES ( date1, hv_notes, hv_eventid, hv_actseqnbr, leid );

    END IF;COMMIT;

    END AddRmaNote;