Sie sind auf Seite 1von 20

Coding Best Practices

Anil Bhat NAGCC

November 2003

Ignorance of Law is NOT AN EXCUSE!!!

Find the code formatting errors !


-- Columns can start here itself SELECT RCT.trx_number, RCT.trx_date, -- MULTIPLE Columns and Commas at the end SUM(APS.amount_due_original) invoice_amount -- Clauses not aligned FROM ra_customer_trx RCT ,ar_payment_schedules APS -- AND at the end WHERE RCT.customer_trx_id = APS.customer_trx_id AND APS.class = INV AND RCT.completed_flag = Y -- Many conditions on one line AND -- AND on a separate line with no conditions RCT.customer_trx_id IN ( SELECT DISTINCT ARA.customer_trx_id -- Wrong FROM ar_receivable_applications ARA -- No alignment WHERE apply_date BETWEEN ADD_MONTHS(SYSDATE,-1) AND SYSDATE) GROUP BY RCT.trx_number ,RCT.trx_date ORDER BY RCT.trx_number;

Alignment of Statements
SELECT RCT.trx_number invoice_number -- Each column on new line ,RCT.trx_date invoice_date -- Comma at the beginning ,SUM(APS.amount_due_original) invoice_amount Expression on new line FROM ra_customer_trx RCT -- SELECT, FROM, WHERE aligned ,ar_payment_schedules APS -- RCT, APS Aliases aligned WHERE RCT.customer_trx_id = APS.customer_trx_id AND APS.class = INV -- Each condition on new Line AND RCT.completed_flag = Y AND RCT.customer_trx_id IN ( -- Opening bracket of Sub-query SELECT DISTINCT ARA.customer_trx_id -- Sub-query new line and indented FROM ar_receivable_applications ARA WHERE apply_date BETWEEN ADD_MONTHS(SYSDATE,-1) AND SYSDATE ) GROUP BY RCT.trx_number -- Group by aligned with SELECT ,RCT.trx_date ORDER BY RCT.trx_number;

Spot some more errors !


-- Get_Segments.sql Create or Replace Package BODY get_Segment as Override varchar2(100) := YES; PROCEDURE xxsegment1_getvalue ( l_org number, l_org_type varchar2) as I number; org varchar2(100); Begin Select organization_name into org from hr_organization_units where organization_id = l_org and organization_type = l_org_type; If org = ABC then I := 10; Elsif org = BCD Then I := 20; if override = YES then I := 25; Else I := 27; End if; End if; INSERT into XXSEGMENT_VALUES values (I); End; End xxSegment1_getvalue;

The corrected package


CREATE OR REPLACE PACKAGE BODY xxgl_get_segment_pkg AS -------------------------------------------------------------------------------------------------- File : XXGETSEG.sql -- Author : Paul Simon -- Version : $Header 1.1 20/11/2003 PSIMON$ -- Description : Procedures to get the GL Segment Values -- History -- ----------------------------------------------------------------------------------------------- 1.0 Paul Simon Created. -- 1.1 Paul Simon Added exceptions. ------------------------------------------------------------------------------------------------GC_OVERRIDE CONSTANT VARCHAR2(100) := YES;
Naming Conventions

File Header

Variable Naming Standards

PROCEDURE Get_Segment1 ( p_org_id IN NUMBER , p_org_type IN VARCHAR2 ) AS

DEFAULT -1

Procedure name of the type Action_Object

lc_org_name VARCHAR2(100); ln_segment_value NUMBER; BEGIN {

Variables declared alphabetically

The corrected package contd.


DBMS_OUTPUT.PUT_LINE(1: Selecting Organization Name..); --- Select the org name based on the org_id and type -BEGIN --{ SELECT ORG.organization_name org_name INTO lc_org_name FROM hr_organization_units ORG , fnd_lookups LKP WHERE ORG.organization_id = p_org_id AND ORG.organization_type = p_org_type AND LKP.lookup_code = ORG.organization_type; EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(ERROR: Retrieving Org Name for || Org ID : ||p_org_id || Org Type : || p_org_type || SQLERRM); ln_segment_value := -1; RAISE; END; --} DBMS_OUTPUT.PUT_LINE(2: Org Name = lc_org_name = || lc_org_name);

Comments

SELECT aligned

Indentation

Keywords and table aliases capitalized

The corrected package contd.


DBMS_OUTPUT.PUT_LINE(3: Deciding Segment Value); DBMS_OUTPUT.PUT_LINE(4: Glbl Override = g_v_override = || g_v_override);

--- Decide on the segment value based on the org name -IF lc_org_name = ABC THEN [ ln_segment_value := 10; ELSIF l_v_org_name = BCD THEN --][ ln_segment_value := 20; IF GC_OVERRIDE = YES THEN [ ln_segment_value := 25; ELSE --][ ln_segment_value := 27; END IF; --] END IF; --]
DBMS_OUTPUT.PUT_LINE(5: Seg Value = ln_segment_value = || ln_segment_value); DBMS_OUTPUT.PUT_LINE(6: Inserting into XXSEGMENT_VALUES);

IF statements aligned

No TAB characters

Debugging Statements

The corrected package contd.


--- Insert the selected value into the table -BEGIN --{ INSERT INTO XXSEGMENT_VALUES ( SEQUENCE_NO , SEGMENT_VALUE ) VALUES ( XXSEGMENT_VALUES_S.NEXTVAL , ln_segment_value ); DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT || rows inserted.); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(ERROR: Inserting into XXSEGMENT_VALUES || SQLERRM); RAISE; END; --} EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(ERROR: Exiting Get_Segment1 abruptly); END; --} END xxgl_get_segment_pkg; --}

All Exceptions handled

Program Exits Gracefully on Error

Only one OTHERS exception per block

Naming Standards and Dates

SELECT

FROM WHERE ..

trx_number , trx_date , TO_CHAR(trx_date) . TO_DATE(attribute2, DD-MON-YYYY) ra_customer_trx , xx_ra_customer_trx_iface

trx_number trx_date trx_date_char sales_date RCT XRCTI3

TO_CHAR(date_column) = :field TRUNC(date_column) = :field date_column BETWEEN start_date AND end_date

- - Can give wrong results - - Performance - - Time component ignored

date_column BETWEEN to_date(01-JAN-03) AND to_date(31-DEC-03)


- - Language and Format assumed

Naming Conventions
V a ria b le C ON S T A N T E X C E P T I ON C h a ra cte r N u mb e r D a te B o o le a n R e co rd V ab ria le Ta lebV a ria b le R e co rd T yp e T a b le T yp e C u rso r REF T yp e

PS: F o r G lo b a l v a r ia b le s r e p la c e l by g .

IN P a ra me te r n .a n .a p_ n a me p_ n a me p_ n a me P_ n a me p_ n a me _ re c p_ n a me _ tb l n .a n .a n .a n .a

OU T P a ra me te r n .a n .a x_ n a me x_ n a me x_ n a me x_ n a me x_ n a me _ re c x_ n a me _ tb l n .a n .a n .a n .a

L_ N A ME u (p p e r ca se ) EX_ N A ME lc_ n a me ln _ n a me ld _ n a me lb _ n a me lr_ n a me lt_ n a me n a me _ r e c_ t yp e n a me _ t b l_ t yp e lcu _ n a me

C U R S OR n a me _ c sr_ t yp e

Error Handling

Handling Abnormal Errors : Reporting Exact Error and Position using lc_error_ variables.

BEGIN lc_error_loc := Get Customer Name; lc_error_debug := Customer Id ||ln_customer_id; SELECT customer_name INTO lc_customer_name FROM ra_customers RC WHERE RC.customer_id = ln_customer_id; EXCEPTION . EXCEPTION At the end of Procedure/Function or Anonymous Block WHEN OTHERS THEN lc_error_msg := SQLERRM; -- Before any SQL Statement as SQLERRM will be cleared. ROLLBACK <savepoint>; DBMS_OUTPUT.PUT_LINE(Oracle Error : ||lc_error_msg|| at ||lc_error_loc|| debug( ||lc_error_debug||); END;

Error Handling General Hints

Program should not exit with Oracle Errors. Error Message to include specific information like exact Error, Where, Why, when and related values. Use lc_error_ variables. Values should be in User Domain ( I.e. dont display Internal Ids). Error Message be in Third Person Dont blame user! Be polite! Messages should be understandable( without abreviations). Make the messages short Error Messages to indicate corrective actions, if possible/required.

Error Handling Some Examples

You have entered wrong period Enter correct period Payment terms is not correct/Payment terms: ID is not correct Payment terms <name> of Invoice : <invoice> is not correct Record for specified inventory_id and organation_id is not found Item: <itemNumber> is either not defined or not attached to organization : <OrgName> Entered item_id is invalid, since, entered item_id and Organization_id not found mtl_system_item Item : <ItemNumber> not defined for organization: <Organization Name>

Error Handling Commit and Rollback

COMMIT only after all operations are successful Use Intermediate SAVEPOINT to flush rollback segment COMMIT should not be done in certain procedures/functions Workflow, those called by other/external procedures. ROLLBACK, in case of errors Only up to beginning of procedure/functions. Include SAVEPOINT beginning, at the beginning of procedure. Display/return all error messages before ROLLBACK, especially if errors are stored in tables.

Error Handling - Example

AS SAVEPOINT beginning; .. SAVEPOINT a; -- Intermediate Savepoints . COMMIT; -- every thing is done, save. EXCEPTION lc_error_msg := SQLERRM; print_errors; -- Custom Procedure ROLLBACK to beginning; DBMS_OUTPUT.. END;

Efficient Statements
Use JOIN instead of Sub-Query Use UNION ALL instead of UNION Use OUTER JOIN, DECODE and GROUP functions to perform multiple operations with single query/statement Write code so that INDEXes can be used. Update/Insert/Delete multiple records in each statements (avoid cursors) Update multiple columns in one UPDATE statement. Avoid duplication of same code/statement unnecessarily!

Efficient Statements

Tools: EXPLAIN PLAN Look for FTS, Base Table usage, appropriate Method of Joining. SET AUTOTRACE ON Look at Statistics : Logical Buffers TKPROF tkprof apps/apps a.trc /tmp/a.prf sort=fchqry, exeqry Look for CPU Time, Logical Buffers and Plan. HINTS- SELECT /*+ hints */ INDEX, ORDERED, LEADING, USE_NL, FIRST_ROWS, RULE.

Applications Standards

Create Tables, Indexes, Sequences in Custom Schema Dont prefix Schema Name to Table Name Dont hardcode Tablespace or Schema Name Dont use _ALL, _TL, _B tables instead use MultiOrg or MLS/NLS views. Provide appropriate Storage Clauses Dont use MAXEXTENTS UNLIMITED Dont forget PCTFREE(5-10%) and PCTUSED (>80%).

Ignorance of Law is NOT AN EXCUSE!!!

Das könnte Ihnen auch gefallen