PL/SQL Coding Conventions<br />fang.yu@moodys.com<br />Dec 28,  2010<br />
Agenda<br />Naming Conventions<br />Coding Style, Format and Comments<br />PL/SQL Best Practices<br />
Naming Conventions<br /><ul><li>Why Naming Convention
Some Facts that Matter
An Appetizer
General Guidelines
Naming Conventions</li></li></ul><li>1.1 Why Naming Convention<br /><ul><li>Easier to read, test, maintain
Higher quality, more robust
Better products
Higher reputation</li></li></ul><li>1.2 Some Facts that Matter<br /><ul><li>30 characters
Case insensitive</li></li></ul><li>1.3 An Appetizer<br />Any problem with this procedure?<br />CREATE PROCEDURE remove_emp...
1.4 General Guidelines <br /><ul><li>Use meaningful and specific names,  abbreviations, table/column alias.
Do not use reserved words as variable names.</li></ul>SELECT  keyword FROM v$reserved_words  <br /><ul><li>Avoid redundant...
1.5 Naming Conventions for Variables<br />
1.6 Naming Conventions for Cursors<br />
1.7 Naming Conventions for Records and Collections<br />
1.8 Naming Conventions for Database Objects<br />
Coding Style, Format and Comments<br /><ul><li>General Coding Style
Some Examples
Tools that format PL/SQL
Code Commenting
View/Trigger Comment Block</li></li></ul><li>2.1 General Coding Style<br /><ul><li>Keywords are written in uppercase, vari...
Indention using tab or 3 spaces. Keep it consistent!
One command per line.
Specify columns explicitly in SELECT and INSERT statements
SQL keywords are right-aligned / left-aligned within a SQL command. Keep it consistent!</li></ul>PROCEDURE set_salary(p_em...
2.2 Some SQL Style Examples<br />SELECT e.job, e.deptno FROM emp e WHERE e.name = 'SCOTT' AND e.sal > 100000<br />SELECT  ...
2.3 Tools that format PL/SQL<br /><ul><li>Instant SQL Formatter  http://www.dpriver.com/pp/sqlformat.htm
Oracle SQL Developer</li></li></ul><li>2.4 Code Commenting<br /><ul><li>pldochttp://pldoc.sourceforge.net/maven-site/</li>...
2.5 View/Trigger Comment Block<br />CREATE OR REPLACE TRIGGER tri_mytab_bi<br />BEFORE INSERT ON mytab<br />FOR EACH ROW <...
PL/SQL Best Practices<br /><ul><li>Literals, Constants and Variables
Data Types
Flow Control
Upcoming SlideShare
Loading in …5
×

Plsql coding conventions

4,569 views

Published on

Brief introduction on PL/SQL coding style

Published in: Technology
2 Comments
1 Like
Statistics
Notes
No Downloads
Views
Total views
4,569
On SlideShare
0
From Embeds
0
Number of Embeds
41
Actions
Shares
0
Downloads
0
Comments
2
Likes
1
Embeds 0
No embeds

No notes for slide

Plsql coding conventions

  1. 1. PL/SQL Coding Conventions<br />fang.yu@moodys.com<br />Dec 28, 2010<br />
  2. 2. Agenda<br />Naming Conventions<br />Coding Style, Format and Comments<br />PL/SQL Best Practices<br />
  3. 3. Naming Conventions<br /><ul><li>Why Naming Convention
  4. 4. Some Facts that Matter
  5. 5. An Appetizer
  6. 6. General Guidelines
  7. 7. Naming Conventions</li></li></ul><li>1.1 Why Naming Convention<br /><ul><li>Easier to read, test, maintain
  8. 8. Higher quality, more robust
  9. 9. Better products
  10. 10. Higher reputation</li></li></ul><li>1.2 Some Facts that Matter<br /><ul><li>30 characters
  11. 11. Case insensitive</li></li></ul><li>1.3 An Appetizer<br />Any problem with this procedure?<br />CREATE PROCEDURE remove_emp_in_dept(depno IN NUMBER)<br />AS<br />BEGIN<br /> DELETE FROM emp WHERE depno = depno;<br />END;/<br />
  12. 12. 1.4 General Guidelines <br /><ul><li>Use meaningful and specific names, abbreviations, table/column alias.
  13. 13. Do not use reserved words as variable names.</li></ul>SELECT  keyword FROM v$reserved_words  <br /><ul><li>Avoid redundant or meaningless prefixes and suffixes.</li></ul>CREATE TABLE demo_table<br />CREATE TABLE demo<br /><ul><li>Do not quote name with double quotes (“)</li></ul>SQL> create table "HelloWorld" (id number);<br />Table created.<br />SQL> select * from helloworld;<br />select * from helloworld<br /> *<br />ERROR at line 1:<br />ORA-00942: table or view does not exist<br />SQL> select * from HelloWorld;<br />select * from HelloWorld<br /> *<br />ERROR at line 1:<br />ORA-00942: table or view does not exist<br />SQL> select * from "HelloWorld";<br />no rows selected<br />
  14. 14. 1.5 Naming Conventions for Variables<br />
  15. 15. 1.6 Naming Conventions for Cursors<br />
  16. 16. 1.7 Naming Conventions for Records and Collections<br />
  17. 17. 1.8 Naming Conventions for Database Objects<br />
  18. 18. Coding Style, Format and Comments<br /><ul><li>General Coding Style
  19. 19. Some Examples
  20. 20. Tools that format PL/SQL
  21. 21. Code Commenting
  22. 22. View/Trigger Comment Block</li></li></ul><li>2.1 General Coding Style<br /><ul><li>Keywords are written in uppercase, variable names are written in lowercase.
  23. 23. Indention using tab or 3 spaces. Keep it consistent!
  24. 24. One command per line.
  25. 25. Specify columns explicitly in SELECT and INSERT statements
  26. 26. SQL keywords are right-aligned / left-aligned within a SQL command. Keep it consistent!</li></ul>PROCEDURE set_salary(p_empno_in IN emp.empno%TYPE)<br />IS<br /> CURSOR l_emp_cur(p_empnoemp.empno%TYPE)<br /> IS<br /> SELECT ename<br /> ,sal<br /> FROM emp<br /> WHERE empno = p_empno<br /> ORDER BY ename;<br />l_empl_emp_cur%ROWTYPE;<br />l_new_salemp.sal%TYPE;<br />BEGIN<br /> OPEN l_emp_cur(p_empno_in);<br /> FETCH l_emp_cur INTO l_emp;<br /> CLOSE l_emp_cur;<br /> -- <br />get_new_salary (p_empno_in => in_empno<br /> , p_sal_out => l_new_sal);<br /> -- Check whether salary has changed <br /> IF l_emp.sal <> l_new_sal THEN<br /> UPDATE emp<br /> SET sal = l_new_sal<br /> WHERE empno = p_empno_in;<br /> END IF;<br />END set_salary;<br />
  27. 27. 2.2 Some SQL Style Examples<br />SELECT e.job, e.deptno FROM emp e WHERE e.name = 'SCOTT' AND e.sal > 100000<br />SELECT <br />e.job,<br />e.deptno<br />FROM <br />emp e<br />WHERE <br /> e.name = 'SCOTT' AND<br /> e.sal > 100000<br />SELECT e.JOB<br />,e.deptno<br /> FROM emp e<br /> WHERE e.name = 'SCOTT' <br /> AND e.sal > 100000<br />SELECT e.JOB<br />, e.deptno<br />FROM emp e<br />WHERE e.name = 'SCOTT'<br />AND e.sal > 100000<br />SELECT e.JOB,<br />e.deptno<br />FROM emp e<br />WHERE e.name = 'SCOTT' <br />AND e.sal > 100000<br />
  28. 28. 2.3 Tools that format PL/SQL<br /><ul><li>Instant SQL Formatter http://www.dpriver.com/pp/sqlformat.htm
  29. 29. Oracle SQL Developer</li></li></ul><li>2.4 Code Commenting<br /><ul><li>pldochttp://pldoc.sourceforge.net/maven-site/</li></ul>PACKAGE pack_syspar IS<br />/** <br />* Project: Test Project (<a href="http://pldoc.sourceforge.net">PLDoc</a>)<br/><br />* Description: System Parameters Management<br/><br />* DB impact: YES<br/><br />* Commit inside: NO<br/><br />* Rollback inside: NO<br/><br />* @headcom<br />*/<br />/** Gets system parameter value.<br />* @paramp_name parameter name<br />* @return parameter value<br />* @throws no_data_found if no parameter with such name found<br />*/<br />FUNCTION get_char<br /> (p_name VARCHAR2)<br />RETURN VARCHAR2;<br />END pack_syspar ;<br />/<br />
  30. 30. 2.5 View/Trigger Comment Block<br />CREATE OR REPLACE TRIGGER tri_mytab_bi<br />BEFORE INSERT ON mytab<br />FOR EACH ROW <br />DECLARE <br /> -- local variables here <br />BEGIN <br /> NULL;<br />END tri_mytab_bi<br />/*******************************************************************<br /> Copyright YYYY by <Company Name> <br /> All Rights Reserved. <br /><Short synopsis of trigger's purpose. Required.> <br /><Optional design notes.> <br />*******************************************************************/ ;<br />/*******************************************************************<br /> Copyright YYYY by <Company Name> <br /> All Rights Reserved. <br /><Short synopsis of trigger's purpose. Required.> <br /><Optional design notes.> <br />*******************************************************************/ <br />CREATE OR REPLACE TRIGGER tri_mytab_bi<br />BEFORE INSERT ON mytab<br />FOR EACH ROW <br />DECLARE <br /> -- local variables here <br />BEGIN <br /> NULL;<br />END tri_mytab_bi;<br />
  31. 31. PL/SQL Best Practices<br /><ul><li>Literals, Constants and Variables
  32. 32. Data Types
  33. 33. Flow Control
  34. 34. Exception Handling
  35. 35. Dynamic SQL
  36. 36. Stored Objects
  37. 37. Other</li></li></ul><li>3.1 Literals, Constants and Variables<br /><ul><li>Avoid using literals in your code, abstract literals behind package constants
  38. 38. Use a function to return a constant if the “constant” value may change at times
  39. 39. Do not use public global variables, use getter/setter or parameters-passing
  40. 40. Never put all of a system’s constants in a single package.
  41. 41. Avoid initializing variables using functions in the declaration section.</li></li></ul><li>3.1 Literals, Constants and Variables (Examples)<br />-- Bad <br />DECLARE <br />l_functionplayer.function_name%TYPE; <br />BEGIN <br /> SELECT p.function<br /> INTO l_function<br /> FROM player p <br /> WHERE … <br /> -- <br /> IF l_function = ‘LEADER’ <br /> THEN <br />-- Good <br />CREATE OR REPLACE PACKAGE pack_constants<br />IS <br />gc_leader CONSTANT player.function_name%TYPE := ‘LEADER’; <br />END pack_constants ; <br />/ <br /> DECLARE <br />l_functionplayer.function_name%TYPE; <br />BEGIN <br /> SELECT p.function INTO l_function FROM player p WHERE … <br /> -- <br /> IF l_function = pack_constants.gc_leader<br /> THEN <br />-- Bad <br />DECLARE <br />l_code_section VARCHAR2(30) := ‘TEST_PCK’; <br />l_company_name VARCHAR2(30) := util_pck.get_company_name(in_id => 47); <br />BEGIN <br /> … <br />END;<br />-- Good <br />DECLARE <br />l_code_section VARCHAR2(30) := ‘TEST_PCK’; <br />l_company_name VARCHAR2(30); <br />BEGIN <br /> <<init>> <br /> BEGIN <br />l_companyName := util_pck.get_company_name(inId => 47); <br />EXCEPTION <br /> WHEN VALUE_ERROR THEN …; <br />END; <br />END;<br />
  42. 42. 3.2 Data Types <br /><ul><li>Anchor parameters and variables using %TYPE (or %ROWTYPE for cursor or entire table).
  43. 43. Use SUBTYPE to avoid hard-coded variable length declarations.
  44. 44. Avoid using CHAR data type.
  45. 45. Never use zero-length strings to substitute NULL.
  46. 46. (CLOB, BLOB or BFILE ) vs. (LONG or LONG RAW)
  47. 47. NUMBER vs. PLS_INTEGER vs. SIMPLE_INTEGER (New in 11g, always not null)
  48. 48. Avoid using ROWID or UROWID (Universal ROWID)</li></li></ul><li>3.2 Data Types (Examples) <br />CREATE OR REPLACE PACKAGE PACK_TYPES <br />AS<br /> SUBTYPE t_oracle_name IS VARCHAR2(30);<br /> SUBTYPE t_oracle_max_varchar IS VARCHAR2(4000);<br /> subtype t_plsql_max_varchar IS VARCHAR2(32767);<br />END PACK_TYPES;<br />/<br />-- Bad <br />l_code_sectionVARCHAR2(30) := ‘TEST_PCK’;<br />-- Good <br />l_code_sectionpack_types.t_oracle_name := ‘TEST_PCK’;<br />-- Bad <br />DECLARE <br />l_ename VARCHAR2(10); <br />BEGIN <br /> SELECT e.ename<br /> INTO l_ename<br /> FROM emp e <br /> WHERE … <br />END;<br />-- Good <br />DECLARE <br />l_enameemp.ename%TYPE; <br />BEGIN <br /> SELECT e.ename<br /> INTO l_ename<br /> FROM emp e <br /> WHERE … <br />END;<br />-- Bad <br />l_char := ‘’;<br />-- Good <br />l_char := NULL;<br />
  49. 49. 3.3 Flow Control<br /><ul><li>Always label your loops
  50. 50. Always use a FOR loop to process the complete cursor results unless you are using bulk operation
  51. 51. Always use a WHILE loop to process a loose array
  52. 52. Always use FIRST..LAST when iterating through collections with a loop
  53. 53. Always use EXIT WHEN instead of an IF statement to exit from a loop
  54. 54. Never EXIT from within any FOR loop, use LOOP or WHILE loop instead
  55. 55. Avoid hard-coded upper or lower bound values with FOR loops
  56. 56. Never issue a RETURN statement inside a loop</li></li></ul><li>3.3 Flow Control (Examples)<br />BEGIN <br /> <<process_employees>> <br /> FOR r_employee IN (SELECT * FROM emp) <br /> LOOP <br /> … <br /> END LOOP process_employees;<br />END; <br />BEGIN <br /> <<process_employees>> <br /> FOR idx IN t_employees.FIRST()..t_employees.LAST() <br /> LOOP <br /> … <br /> END LOOP process_employees; <br />END; <br />DECLARE <br />l_index PLS_INTEGER; <br />BEGIN <br />l_index := t_employees.FIRST(); <br /> <<ProcessEmployees>> <br />WHILE l_index IS NOT NULL <br /> LOOP <br /> … <br />l_index := t_employees.NEXT(l_index); <br /> END LOOP process_employees; <br />END; <br />-- Bad <br />BEGIN <br /> <<process_employees>> <br /> LOOP <br /> ... <br /> IF ... <br /> THEN <br /> EXIT process_employees; <br /> END IF; <br /> ... <br /> END LOOP process_employees; <br />END;<br />-- Good <br />BEGIN <br /> <<process_employees>> <br /> LOOP <br /> ... <br />EXIT process_employees WHEN (...); <br /> END LOOP process_employees; <br />END; <br />
  57. 57. 3.4 Exception Handling<br /><ul><li>Never handle unnamed exceptions using the error number
  58. 58. Never assign predefined exception names to user defined exceptions
  59. 59. Avoid use of WHEN OTHERS clause in an exception section without any other specific handlers
  60. 60. Avoid use of EXCEPTION_INIT pragma for -20, NNN error (-20,999 ~ -20,000)
  61. 61. Use DBMS_UTILITY.format_error_stack instead of SQLERRM to obtain the full error message
  62. 62. Replace status codes with exception handling within PL/SQL</li></li></ul><li>3.4 Exception Handling (Examples)<br />-- Bad <br />-- ORA-00001: unique constraint violated<br />BEGIN <br /> ... <br />EXCEPTION <br />WHEN OTHERS THEN <br />IF SQLCODE = -1 <br /> THEN <br /> ... <br /> END IF; <br />END;<br />-- Good <br />DECLARE <br />e_employee_exists EXCEPTION; <br /> PRAGMA EXCEPTION_INIT(-1, e_employee_exists); <br /> ... <br />BEGIN <br /> ... <br />EXCEPTION <br />WHEN e_employee_exists THEN <br /> ... <br />END;<br />-- Good <br />EXCEPTION <br />WHEN DUP_VAL_ON_INDEX <br /> THEN <br />update_instead (...); <br /> WHEN OTHERS <br /> THEN <br /> err.log; <br /> RAISE; <br />
  63. 63. 3.5 Dynamic SQL<br /><ul><li>Always use a string variable to execute dynamic SQL (easier for debug)
  64. 64. Use bind variables. Do not concatenate strings unless needed to identify schema or table/view.
  65. 65. Format dynamic SQL strings as nicely as in static SQL.</li></li></ul><li>3.5 Dynamic SQL (Examples)<br />-- Bad <br />DECLARE <br />l_empnoemp.empno%TYPE := 4711; <br />BEGIN <br /> EXECUTE IMMEDIATE ‘DELETE FROM emp WHERE epno = :p_empno’ USING l_empno; <br />END;<br />-- Good <br />DECLARE <br />l_empnoemp.empno%TYPE := 4711; <br />l_sql VARCHAR2(32767); <br />BEGIN <br />l_sql := ‘DELETE FROM emp WHERE epno = :p_empno’; <br /> EXECUTE IMMEDIATE l_sql USING l_empno; <br />EXCEPTION <br /> WHEN others <br /> THEN <br /> DBMS_OUTPUT.PUT_LINE(l_sql); <br />END;<br />
  66. 66. 3.6 Stored Objects<br /><ul><li>Try to keep packages small. Include only few procedures and functions that are used in the same context.
  67. 67. Always use forward declaration for private functions and procedures in packages.
  68. 68. Avoid standalone procedures or functions – put them in packages
  69. 69. Avoid using RETURN statements in a procedure(one way in one way out)
  70. 70. Try to use no more than one RETURN statement within a function
  71. 71. Never use OUT parameters to return values from a function</li></li></ul><li>3.7 CASE / IF / DECODE / NVL / NVL2 / COALESCE<br /><ul><li>Try to use CASE rather than an IF statement with multiple ELSIF paths
  72. 72. Try to use CASE rather than DECODE.
  73. 73. Always use COALESCE instead of NVL, if parameter 2 of the NVL function is a function call or a SELECT statement.
  74. 74. Always use CASE instead of NVL2 if parameter 2 or 3 of NVL2 is either a function call or a SELECT statement.
  75. 75. The NVL function always evaluates both parameters before deciding which one to use. This can be harmful if parameter 2 is either a function call or a select statement, as it will be executed regardless of whether parameter 1 contains a NULL value or not.
  76. 76. The COALESCE function does not have this drawback.
  77. 77. NVL2 is similar.
  78. 78. DECODE cannot be used in PL/SQL</li></li></ul><li>3.7 CASE / IF / DECODE / NVL / NVL2 / COALESCE (e.g.)<br />-- Bad <br />IF l_color = ′red′ <br />THEN <br /> ... <br />ELSIF l_color = ′blue′ <br />THEN <br /> ... <br />ELSIF l_color = ′black′ <br />THEN <br /> ...<br />-- Good <br />CASE l_color<br /> WHEN ′red′ THEN ... <br /> WHEN ′blue′ THEN ... <br /> WHEN ′black′ THEN ... <br />END<br />-- Bad <br />SELECT NVL(dummy, function_call()) FROM dual;<br />-- Good <br />SELECT COALESCE(dummy, function_call()) FROM dual;<br />-- Bad <br />SELECT NVL2(dummy, ‘Yes’, ‘No’) FROM dual; <br />-- Good <br />SELECT CASE <br /> WHEN dummy IS NULL THEN ‘No’ <br /> ELSE ‘Yes’ <br /> END <br /> FROM dual;<br />
  79. 79. Thanks!<br />Q&A<br />
  80. 80. © 2009 Moody’s Analytics, Inc. and/or its licensors and affiliates (collectively, “MOODY’S”). All rights reserved. ALL INFORMATION CONTAINED HEREIN IS PROTECTED BY COPYRIGHT LAW AND NONE OF SUCH INFORMATION MAY BE COPIED OR OTHERWISE REPRODUCED, REPACKAGED, FURTHER TRANSMITTED, TRANSFERRED, DISSEMINATED, REDISTRIBUTED OR RESOLD, OR STORED FOR SUBSEQUENT USE FOR ANY SUCH PURPOSE, IN WHOLE OR IN PART, IN ANY FORM OR MANNER OR BY ANY MEANS WHATSOEVER, BY ANY PERSON WITHOUT MOODY’S PRIOR WRITTEN CONSENT. All information contained herein is obtained by MOODY’S from sources believed by it to be accurate and reliable. Because of the possibility of human or mechanical error as well as other factors, however, all information contained herein is provided “AS IS” without warranty of any kind. Under no circumstances shall MOODY’S have any liability to any person or entity for (a) any loss or damage in whole or in part caused by, resulting from, or relating to, any error (negligent or otherwise) or other circumstance or contingency within or outside the control of MOODY’S or any of its directors, officers, employees or agents in connection with the procurement, collection, compilation, analysis, interpretation, communication, publication or delivery of any such information, or (b) any direct, indirect, special, consequential, compensatory or incidental damages whatsoever (including without limitation, lost profits), even if MOODY’S is advised in advance of the possibility of such damages, resulting from the use of or inability to use, any such information. The ratings, financial reporting analysis, projections, and other observations, if any, constituting part of the information contained herein are, and must be construed solely as, statements of opinion and not statements of fact or recommendations to purchase, sell or hold any securities. NO WARRANTY, EXPRESS OR IMPLIED, AS TO THE ACCURACY, TIMELINESS, COMPLETENESS, MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OF ANY SUCH RATING OR OTHER OPINION OR INFORMATION IS GIVEN OR MADE BY MOODY’S IN ANY FORM OR MANNER WHATSOEVER. Each rating or other opinion must be weighed solely as one factor in any investment decision made by or on behalf of any user of the information contained herein, and each such user must accordingly make its own study and evaluation of each security and of each issuer and guarantor of, and each provider of credit support for, each security that it may consider purchasing, holding, or selling.<br />

×