PL/SQL Development


Published on

PL/SQL & Java Development

Published in: Technology
1 Like
  • Be the first to comment

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

PL/SQL Development

  1. 1. Diego  Thanh  Nguyen  PL/SQL  DEVELOPMENT  10/8/12   1  
  2. 2. Table  Of  Content  q I.  Test-­‐Driven  PL/SQL  Development   v I.1.  Front-­‐end  &  Back-­‐end   v I.2.  Development  WorkKlow  q II.  Exception  Handling  Architecture  q III.  Optimize  SQL  in  PL/SQL  q IV.  Java  &  PL/SQL   v IV.1.  Client  Server  Java/PLSQL  Architecture   v IV.2.  Java  -­‐  PL/SQL:  Ad-­‐hoc  Call   v IV.3.  Java  -­‐  PL/SQL:  Function/Procedure  Call     10/8/12   2  
  3. 3. I.1.  Front-­‐end  &  Back-­‐end  §  We  usually  just  talk   Browser   Java   about  front-­‐end  and   Frontend   Oracle     back-­‐end,  but  theres          Developer   more  to  it  than  that.   "Assign  calls"  §  Developers  spend   Application  Logic   app_call_mgr   most  of  their  time  in   B "Is  call  open?"   a Business  Rules   cm_calls_rp.is_open   the  top  two  layers.   "Log  error"   c Backend   Infrastructure   –  But  they  often   em_errors   k (in  the     "Parse  string"   dont  have  clearly   Generic  Utilities   e Oracle  Database)   tb_string_utils   deKined   "Add  new  call"   boundaries.   n Data  Access   cm_calls_cp.ins   d "Call  Table"   Data  (tables)   cm_calls   10/8/12   3  
  4. 4. I.2.  Development  WorkLlow  Application  Preparation   1 Coding     7 The  Build     Test  and     Cycle   Conventions   Review   SQL   To  QA  /   Access   Debug   Production   Error   Build  /     Mgt   6 Fix  Code  Single    Unit     2 3 4 5Preparation   DeKine   Construct   DeKine     Build     Req’ments   Header   Tests   Test  Code   Post-­‐   Post-­‐   Production   Production   Bug   Enhance.   Report   Request   10/8/12   4  
  5. 5. I.3.  Testing  q Functional/System  Tests   v Performed  by  QA  teams  and  users,  tests  entire   application.  q Stress  Tests   v Program  works  for  1  user,  how  about  10,000?   Usually  done  by  DBAs  and  system  admins.     v Quests  Benchmark  Factory  automates  this  process.  q Unit  Tests,  aka  ”Programmer  Tests"   v The  test  of  a  single  unit  of  code.   v These  are  the  responsibility  of  developers,  of  the   people  who  wrote  the  program.  q All  testing  is  important,  but  unit  tests  are  the   most  fundamental  kind  of  testing.     10/8/12   5  
  6. 6. II.1.  Error  Management  q Manage  errors  effectively  and  consistently:   v  Errors  are  raised,  handled,  logged  and   communicated  in  a  consistent,  robust  manner.  q Some  special  issues  for  PL/SQL  developers   v The  EXCEPTION  datatype   v How  to  Kind  the  line  on  which  the  error  is  raised?   v Communication  with  non-­‐PL/SQL  host  environments  q Achieving  ideal  error  management   v DeKine  your  requirements  clearly   v PL/SQL  error  management  &  best  practices   10/8/12   6  
  7. 7. II.2.  PL/SQL  Error  Management    q DeKining  exceptions   v Give  name  to  Error  with  EXCEPTION_INIT  PRAGMA  q Raising  exceptions   v RAISE_APPLICATION_ERROR:  communicates  speciKic   error  back  to  a  non-­‐PL/SQL  host  environment  q DML  aren’t  rolled  back  when  exception  is  raised   v Rollback  Handling   v Log  information  is  committed,  while  leaving  the   business  transaction  unresolved  q Handing  exceptions   10/8/12   7  
  8. 8. II.3.  Handing  Exceptions  q The  EXCEPTION  section  consolidates  all  error   handling  logic  in  a  block.   v But  only  traps  errors  raised  in  executable  section  of  block.  q Several  useful  functions  usually  come  into  play:   v SQLCODE  and  SQLERRM   v DBMS_UTILITY.FORMAT_ERROR_STACK   v DBMS_UTILITY.FORMAT_ERROR_BACKTRACE  q The  DBMS_ERRLOG  package   v Quick  and  easy  logging  of  DML  errors.  q The  AFTER  SERVERERROR  trigger   v Instance-­‐wide  error  handling:  most  useful  for  non-­‐PL/SQL   front  ends  executing  SQL  statements  directly.   10/8/12   8  
  9. 9. II.4.  Best  Practices  for  Error  Management  q Some  general  guidelines  -­‐  standards  for  logging   mechanisms,  error  message  text;  must  consistent   v Avoid  hard-­‐coding  of  Error  Numbers  and  Messages.   v Build  and  use  reusable  components  for  Raising,   Handling  and  Logging  Errors.  q Application-­‐level  code  should  not  contain:   v RAISE_APPLICATION_ERROR:  dont  leave  it  to  the   developer  to  decide  how  to  raise.   v PRAGMA  EXCEPTION_INIT:  avoid  duplication  of  error   deKinitions.  q Object-­‐like  representation  of  an  exception  (DB)   10/8/12   9  
  10. 10. II.4.1.  Prototype  Exception  Manager   ² The  rule:  developers  should  only  call  a  pre-­‐ deLined  handler  inside  an  exception  section   v Easier  for  developers  to  write  consistent,  high-­‐quality  code   v They  dont  have  to  make  decisions  about  form  of  log  &  how   the  process  should  be  stopped   PACKAGE  errpkg   IS   Generic          PROCEDURE  raise  (err_in  IN  PLS_INTEGER);  EXCEPTION        PROCEDURE  raise  (err_in  in  VARCHAR2);   Raises        WHEN  NO_DATA_FOUND          THEN          PROCEDURE  record_and_stop  (              errpkg.record_and_continue  (              err_in  IN  PLS_INTEGER  :=  SQLCODE                    SQLCODE,     Record            ,msg_in  IN  VARCHAR2  :=  NULL);                      Not  Exist    ||  TO_CHAR  (v_id));   and  Stop            PROCEDURE  record_and_continue  (        WHEN  OTHERS              err_in  IN  PLS_INTEGER  :=  SQLCODE        THEN   Record            ,msg_in  IN  VARCHAR2  :=  NULL);              errpkg.record_and_stop;     &  Continue    END;   END  errpkg;   10/8/12   10  
  11. 11. III.  Optimize  SQL  in  PL/SQL  q Advantage  of  PL/SQL  enhancements  for  SQL.   v III.1.  BULK  COLLECT   Ø Use  with  implicit  and  explicit  queries.   Ø Move  data  from  tables  into  collections.   v III.2.  FORALL   Ø Use  with  inserts,  updates  and  deletes.   Ø Move  data  from  collections  to  tables.   v III.3.  Table  functions  q III.4.  Top  Tip:  Stop  Writing  So  Much  SQL   v A  key  objective  of  this  presentation  is  to  have  you  stop  taking   SQL  statements  for  granted  inside  your  PL/SQL  code.   v Instead,  you  should  think  hard  about  when,  where  and  how   SQL  statements  should  be  written  in  your  code.   10/8/12   11  
  12. 12. III.1.  SQL  and  PL/SQL  Oracle  Server   PL/SQL  Runtime  Engine   SQL  Engine   PL/SQL  block   Procedural   statement   FOR  rec  IN  emp_cur  LOOP   executor      UPDATE  employee     SQL            SET  salary  =  ...   statement        WHERE  employee_id  =     executor                    rec.employee_id;   END  LOOP;   Performance  penalty   for  many  “context   switches”   12  
  13. 13. III.1.  Different  process  with  FORALL  Oracle  server   PL/SQL  Runtime  Engine   SQL  Engine   PL/SQL  block   Procedural   statement   FORALL  indx  IN     executor                list_of_emps.FIRST..   SQL                list_of_emps.LAST   statement    UPDATE  employee     executor          SET  salary  =  ...      WHERE  employee_id  =                    list_of_emps(indx);   Much  less  overhead  for   context  switching     13
  14. 14. III.1.  Use  BULK  COLLECT  INTO  for  Queries   DECLARE   Declare  a        TYPE  employees_aat  IS  TABLE  OF  employees%ROWTYPE   collection  of              INDEX  BY  BINARY_INTEGER;   records  to  hold          l_employees  employees_aat;  the  queried  data.     BEGIN        SELECT  *        BULK  COLLECT  INTO  l_employees   Use  BULK            FROM  employees;   COLLECT  to                    FOR  indx  IN  1  ..  l_employees.COUNT    retrieve  all  rows.          LOOP              process_employee  (l_employees(indx));        END  LOOP;   END;   Iterate  through   the  collection   contents  with  a   WARNING!  BULK  COLLECT  will  not  raise   loop.     NO_DATA_FOUND  if  no  rows  are  found.   Always  check  contents  of  collection  to  conLirm  that   something  was  retrieved.   14  
  15. 15. III.2.  FORALL  Bulk  Bind  Statement  q Instead  of  executing  repetitive,  individual  DML   statements,  you  can  write  your  code  like  this:   PROCEDURE  upd_for_dept  (...)    IS   BEGIN        FORALL  indx  IN  list_of_emps.FIRST  ..  list_of_emps.LAST              UPDATE  employee                      SET  salary  =  newsal_in                  WHERE  employee_id  =  list_of_emps  (indx);   END;  q Things  to  be  aware  of:   v  You  MUST  know  how  to  use  collections  to  use  this  feature!   v  Only  a  single  DML  statement  is  allowed  per  FORALL.   v  New  cursor  attributes:  SQL%BULK_ROWCOUNT  returns  number  of  rows  affected   by  each  row  in  array.  SQL%BULK_EXCEPTIONS...   v  Use  SAVE  EXCEPTIONS  to  continue  past  errors.  q When  Cursor  FOR  Loop  vs.  BULK  COLLECT?   v If  you  want  to  do  complex  processing  on  each  row  as  it  is  queried  –   and  possibly  halt  further  fetching.     15
  16. 16. III.2.  Tips  and  Fine  Points    q BULK  COLLECT   v Collection  is  always  Lilled  sequentially,  starting  at  row  1.   v Production-­‐quality  code  should  generally  use  the  LIMIT  clause  to   avoid  excessive  memory  usage.   v Note:  Oracle  will  automatically  optimize  cursor  FOR  loops  to  BULK   COLLECT  performance  levels.  q FORALL   v Use  whenever  executing  multiple  single-­‐row  DML  statements.   v Used  with  Collection;  Collection  subscripts  cannot  be  expressions.   v Cannot  reference  Lields  of  collection-­‐based  records  inside  FORALL.   Ø But  you  can  use  FORALL  to  insert  &  update  entire  records.   v Use  the  INDICES  OF  clause  to  use  only  the  row  numbers  deLined  in   another  array.   v Use  VALUES  OF  clause  to  use  only  values  deLined  in  another  array.     10/8/12   16  
  17. 17. III.3.  Table  Function  q The  Wonder  Of  Table  Functions   v Table  function  allow  to  perform  arbitrarily  complex  transformations   of  data  and  then  make  that  data  available  through  a  query.   Ø Not  everything  can  be  done  in  SQL.   v Combined  with  REF  CURSORs,  you  can  now  more  easily  transfer  data   from  within  PL/SQL  to  host  environments.   Ø Java,  works  very  smoothly  with  cursor  variables  q Building  a  table  function   v Return  nested  table  or  varray  based  on  schema-­‐deLined  type.   Ø Types  deLined  –  only  used  with  pipelined  table  functions.   v The  function  header  and  the  way  it  is  called  must  be  SQL-­‐compatible:   all  parameters  use  SQL  types;  no  named  notation.   Ø In  some  cases  (streaming  and  pipelined  functions),  the  IN   parameter  must  be  a  cursor  variable  -­‐-­‐  a  query  result  set.   10/8/12   17  
  18. 18. III.3.  Streaming  Data  with  Table  Functions  q "stream"  data  through  several  stages  within  a  single   SQL  statement.   v Example:  transform  one  row  in  the  stocktable  to  two  rows  in   the  tickertable.   CREATE OR REPLACE PACKAGE refcur_pkg IS TYPE refcur_t IS REF CURSOR RETURN stocktable%ROWTYPE; END refcur_pkg; / CREATE OR REPLACE FUNCTION stockpivot (dataset refcur_pkg.refcur_t) RETURN tickertypeset ... BEGIN INSERT INTO tickertable SELECT * FROM TABLE (stockpivot (CURSOR (SELECT * FROM stocktable))); END; / 10/8/12   18  
  19. 19. III.3.  Piping  rows  out  from  Pipelined  function  q Return  data  iteratively,  asynchronous  to  termination  of   function.  As  data  is  produced  within  the  function,  it  is   passed  back  to  the  calling  process/query.   CREATE  FUNCTION  stockpivot  (p  refcur_pkg.refcur_t)        RETURN  tickertypeset   Add  PIPELINED   keyword  to  header        PIPELINED     IS        out_rec      tickertype    :=                  tickertype  (NULL,  NULL,  NULL);        in_rec        p%ROWTYPE;   BEGIN        LOOP              FETCH  p  INTO  in_rec;              EXIT  WHEN  p%NOTFOUND;   Pipe  a  row  of  data              out_rec.ticker  :=  in_rec.ticker;  back  to  calling  block              out_rec.pricetype  :=  O;   or  query              out_rec.price  :=  in_rec.openprice;              PIPE  ROW  (out_rec);        END  LOOP;        CLOSE  p;  RETURN...nothing  at        RETURN;   all!   END;   10/8/12   19  
  20. 20. III.4.  Top  Tip:  Stop  Writing  So  Much  SQL  q Bottom  line:  if  everyone  writes  SQL   Order  Entry   whenever  and  wherever  they  want  to,  it   Program   is  very  difLicult  to  maintain  and   optimize  the  code.  q General  principle:  Ligure  out  what  is   Order   Item   volatile  and  then  hide  that  stuff  behind   Table   Table   a  layer  of  code  to  minimize  impact  on   Application   application  logic.   Code  q Single  Point  of  (SQL)  Robust  DeLinition:   if  same  statement  appears  in  multiple   Intermediate  Layer   places  in  application  code,  very  difLicult   to  maintain  and  optimize  that  code.  q Avoid  SQL  Repetition   Order   Item   Table   Table   10/8/12   20  
  21. 21. IV.1.  Client  Server  Java/PLSQL  Architecture  q PL/SQL  Programming  Language:   v If/then/else;  Loops;Function  calls   v Transactional   v Procedural   10/8/12   21  
  22. 22. IV.2.  Ways  to  call  PL/SQL  q ADHOC   v Send  the  PL/SQL  block  of  code  from  the  Client-­‐Java   program  to  the  Server  for  processing.   v Query  based  on  Prepared  Statement  q FUNCTION   v Client  Side  calls  a  PL/SQL  function  in  Oracle.       PL/SQL  is  already  compiled  and  loaded  in  Oracle.   v Function  will  return  a  value  q PROCEDURE   v Client  calls  a  PL/SQL  procedure   v Similar  to  function,  but  does  not  return  values.   10/8/12   22  
  23. 23. IV.2.  ADHOC:  PL/SQL  Example  PreparedStatement  ps=null;    sSQL=new  String("declare"  +      "            l_id  number:=0;"  +      "            ret  number:=0;"  +      "            lssno  varchar2(32):=?;"  +      1      "            error_msg  varchar2(1026):=null;"  +      "  BEGIN"  +      "        select  count(*)  into  ret  from  person  where  SSNO=  lssno  ;"  +   2      "        if(ret=0)  then"  +      "          insert  into  person(id,ssno)  values(seq_id.nextval,  lssno)  returning  id  into  ret;"  +      "        end  if;"  +      "        ?:=ret;"  +      "    EXCEPTION  WHEN  OTHERS  THEN"  +   3      "        ?:=SQLERRM;"  +        "  END;");   4  ps  =connection.prepareStatement(sbSQL.toString());  int  indx=1;   5    ps.setString(indx++,SSNO);    int  rettype=Types.INTEGER;  ps.registerOutParameter(indx++,rettype);   6    rettype=Types.VARCHAR;  ps.registerOutParameter(indx++,rettype);    ps.executeUpdate();  l_sError=ps.getString(2);  if(l_sError!=null)  {    System.err.println("PL/SQL  Error:  "  +  l_sError);              return;   7  }else  {      ret=ps.getInt(1);      System.out.println("New  USERID:  "  +  ret);  }   10/8/12   23  
  24. 24. IV.3.  Java  PL/SQL:  Function/Procedure  Call   import  java.sql.*;  q Key  Things  to  Note:   import  oracle.sql.*;   …    PreparedStatement  ps  =null;   v Minimize  SQL  code  on    ArrayDescriptor  desc  =   ArrayDescriptor.createDescriptor("JOEL.STR_VARRAY”,m_Conn);     client  side.    String  sCar="";    String  cars[]=new  String[10];     v loaded  into  Oracle  once  at    for(int  i=0;i<10;i++)    {                          sCar="carX"+i;                                      //  CONTRIVE  A  NAME  of  a  CAR   install  time.                          cars[i]=new  String(sCar);    }     v Ready  for  portability     ARRAY  array3  =  new  ARRAY  (desc,  m_Conn,  cars);     String  sql=new  String("{call     §  Within  Oracle  –  yes   api_person_pkg.storePersonCar(joelt,?)  }");     §  JDBC  Standard  -­‐  using  other   ps=  m_Conn.prepareStatement(sql);     database  –  perhaps   //  Set  the  values  to  insert     ((oracle.jdbc.driver.OraclePreparedStatement)ps).setARRAY(1,   §  SQL  Standard  -­‐  SQL92  syntax?   array3);     v Consider  using  global   //  Insert  the  new  row     ps.executeUpdate();   temporary  table.       m_Conn.commit();   10/8/12   24  
  25. 25. III.3.  Calling  PL/SQL  Procedures  q Step1:  Create  and  Prepare  a  CallableStatement  Object   v CallableStatement  myCallableStatement  =                                                                                            myConnection.prepareCall(                                                                                        "{call  update_product_price(?,  ?)}”);  q Step2:  Provide  Parameter  Values   v myCallableStatement.setDouble(2,  1.1);  q Step3:  Call  the  execute()  Method   v myCallableStatement.execute();   v myCallableStatement.close();   10/8/12   25  
  26. 26. III.3.  Calling  PL/SQL  Functions  q Step  1:  Create  and  Prepare  a  CallableStatement  Object   v CallableStatement  myCallableStatement  =                                                                                            myConnection.prepareCall(                                                                                        "{call  update_product_price_func  (?,  ?)}”);  q Step  2:  Register  the  Output  Parameter   v myCallableStatement.registerOutParameter(1,java.sql.Types.INTEGER);  q Step2:  Provide  Parameter  Values   v myCallableStatement.setInt(2,  1);  q Step  4:  Run  the  CallableStatement   v myCallableStatement.execute();  q Step  5:  Read  the  Return  Value   v int  result  =  myCallableStatement.getInt(1);   v myCallableStatement.close();   10/8/12   26