writing pl/sql programs in oracle 12c

41
Wri$ng PL/SQL Programs in Oracle 12c By Michael McLaughlin

Upload: buituyen

Post on 01-Jan-2017

318 views

Category:

Documents


6 download

TRANSCRIPT

Page 1: Writing PL/SQL Programs in Oracle 12c

Wri$ng  PL/SQL  Programs  in  Oracle  12c  

By  Michael  McLaughlin  

Page 2: Writing PL/SQL Programs in Oracle 12c

Objec$ves  

•  Cache  invoker  rights  func$ons  •  White  lis$ng  callers  –  Func$ons  –  Procedures  –  Packages  –  Object  types  

•  WITH  clause  PL/SQL  func$ons  •  Use  PL/SQL  types  in  SQL  statements  

Page 3: Writing PL/SQL Programs in Oracle 12c

Objec$ves  (con$nued)  

•  Oracle  type  evolu$on  –  Discovering  type  dependencies  –  Cascading  type  changes  

•  Using  iden$ty  columns  in  transac$ons  •  Working  with  invisible  columns  •  UTL_CALL_STACK  Package  •  Top’n  Queries  

Page 4: Writing PL/SQL Programs in Oracle 12c

Cache  Invoker  Rights  Func$ons  Added  in  Oracle  Database  12c  

•  Adds  the  CURRENT_USER  to  cache  •  Like  Oracle  Database  11g,  the  func$on  must  return  a  scalar  data  type  

Page 5: Writing PL/SQL Programs in Oracle 12c

White  List  Callers  Func$ons  

SQL> CREATE OR REPLACE FUNCTION library 2 ( pv_message VARCHAR2 ) RETURN VARCHAR2 3 ACCESSIBLE BY 4 ( FUNCTION video.gateway 5 , PROCEDURE video.backdoor 6 , PACKAGE video.api 7 , TYPE video.hobbit ) IS 8 lv_message VARCHAR2(20) := 'Hello '; 9 BEGIN 10 lv_message := lv_message || pv_message || '!'; 11 RETURN lv_message; 12 END; 13 /

ACCESSIBLE  BY  clause  white  lists  callers  

Page 6: Writing PL/SQL Programs in Oracle 12c

White  List  Callers  Invalidates  or  disallows  compila$on  with  dependencies  

SQL> CREATE OR REPLACE FUNCTION black_knight 2 ( pv_message VARCHAR2 ) RETURN VARCHAR2 IS 3 BEGIN 4 RETURN library(pv_message); 5 END; 6 /

SQL> show errors Errors for FUNCTION BLACK_KNIGHT: LINE/COL ERROR -------- ---------------------------------------------- 4/3 PL/SQL: Statement ignored 4/10 PLS-00904: insufficient privilege to access object LIBRARY

Page 7: Writing PL/SQL Programs in Oracle 12c

White  List  Callers  Package  Specifica$on  ONLY  

SQL> CREATE OR REPLACE PACKAGE small_one 2 ACCESSIBLE BY 3 ( FUNCTION video.gateway 4 , PROCEDURE video.backdoor 5 , PACKAGE video.api 6 , TYPE video.hobbit ) IS 7 FUNCTION add 8 ( lv_a NUMBER 9 , lv_b NUMBER ) RETURN NUMBER; 10 END small_one; 11 /

Page 8: Writing PL/SQL Programs in Oracle 12c

White  List  Callers  Object  Types  

SQL> CREATE OR REPLACE TYPE hello_there 2 ACCESSIBLE BY (FUNCTION white_hat) IS OBJECT 3 ( who VARCHAR2(20) 4 , CONSTRUCTOR FUNCTION hello_there 5 RETURN SELF AS RESULT 6 , CONSTRUCTOR FUNCTION hello_there 7 ( who VARCHAR2 ) 8 RETURN SELF AS RESULT 9 , MEMBER FUNCTION get_who RETURN VARCHAR2 10 , MEMBER PROCEDURE set_who (who VARCHAR2) 11 , MEMBER FUNCTION to_string RETURN VARCHAR2 ) 12 INSTANTIABLE NOT FINAL; 13 /

Page 9: Writing PL/SQL Programs in Oracle 12c

WITH  Clause  PL/SQL  Func$ons    Implemented  in  Oracle  Database  12c  

•  You  can  now  embed  a  PL/SQL  pass-­‐by-­‐value  func$on  inside  a  SQL  WITH  clause  

•  The  PL/SQL  func$on  is  only  available  within  the  scope  of  the  SQL  SELECT  statement  

Page 10: Writing PL/SQL Programs in Oracle 12c

WITH  Clause  PL/SQL  Func$ons  Implemented  in  Oracle  Database  12c  

•  Tricky  to  implement  because  you  must  disable  the  SQLTERMINATOR  environment  value  in  the  SQL*Plus  CLI  environment  –  Requires  direct  implementa$on  in  SQL*Plus  –  Query  can’t  run  independently  outside  of  SQL*Plus  –  Embed the query inside a view to call from other

programs

Page 11: Writing PL/SQL Programs in Oracle 12c

WITH  Clause  PL/SQL  Func$ons  Implemented  in  Oracle  Database  12c  

SQL> SET SQLTERMINATOR OFF SQL> WITH 2 FUNCTION glue 3 ( pv_first_name VARCHAR2 4 , pv_last_name VARCHAR2) RETURN VARCHAR2 IS 5 lv_full_name VARCHAR2(100); 6 BEGIN 7 lv_full_name := pv_first_name || ' ' || pv_last_name; 8 RETURN lv_full_name; 9 END; 10 SELECT glue(a.first_name,a.last_name) AS person 11 FROM actor a 12 /

Page 12: Writing PL/SQL Programs in Oracle 12c

PL/SQL  Data  Type  in  SQL  Statements  Implemented  in  Oracle  Database  12c  

•  You  can  now  embed  a  local  PL/SQL  variable  that  uses  a  PL/SQL  data  type  in  a  SQL  statement  

•  Tricky  to  implement  because  you  must  –  Declare  the  PL/SQL  data  type  in  a  package  or  local  block  –  Declare  a  local  variable  that  uses  the  user-­‐defined  data  type  in  the  local  block  

Page 13: Writing PL/SQL Programs in Oracle 12c

PL/SQL  Data  Type  in  SQL  Statements  Example,  Part  #1  in  Oracle  Database  12c  

SQL> CREATE OR REPLACE PACKAGE type_defs IS 2 TYPE plsql_table IS TABLE OF VARCHAR2(20) 3 INDEX BY BINARY_INTEGER; 4 END type_defs; 5 /

Declare  a  PL/SQL  data  type  in  a  package  specifica$on  

Page 14: Writing PL/SQL Programs in Oracle 12c

PL/SQL  Data  Type  in  SQL  Statements  Example,  Part  #2  in  Oracle  Database  12c  (con$nued)  

SQL> CREATE TABLE honeymooner 2 ( honeymooner_id NUMBER 3 GENERATED ALWAYS AS IDENTITY 4 , person VARCHAR2(20)); SQL> INSERT INTO honeymooner (person) 2 VALUES ('Ralph Kramden'); SQL> INSERT INTO honeymooner (person) 2 VALUES ('Alice Kramden'); SQL> INSERT INTO honeymooner (person) 2 VALUES ('Edward Norton'); SQL> INSERT INTO honeymooner (person) 2 VALUES ('Thelma Norton');

Page 15: Writing PL/SQL Programs in Oracle 12c

PL/SQL  Data  Type  in  SQL  Statements  Example,  Part  #3  in  Oracle  Database  12c  (con$nued)  

SQL> CREATE OR REPLACE FUNCTION implicit_convert 2 RETURN type_defs.plsql_table IS 3 lv_index NUMBER := 1; -- Counter 4 lv_list TYPE_DEFS.PLSQL_TABLE; -- Collection 5 CURSOR c IS SELECT person FROM honeymooners; 6 BEGIN 7 FOR i IN c LOOP 8 lv_list(lv_index) := i.person; 9 lv_index := lv_index + 1; 10 END LOOP; 11 RETURN lv_list; -- Return local collection. 12 END; 13 /

Page 16: Writing PL/SQL Programs in Oracle 12c

PL/SQL  Data  Type  in  SQL  Statements  Example,  Part  #4  in  Oracle  Database  12c  (con$nued)  

SQL> DECLARE 2 list TYPE_DEFS.PLSQL_TABLE; 3 BEGIN 4 list := implicit_convert; 5 FOR i IN (SELECT column_value 6 FROM TABLE(list)) LOOP 7 dbms_output.put_line(i.column_value); 8 END LOOP; 9 END; 10 /

You  must  declare  a  local  variable  of  the  PL/SQL  data  type  

Page 17: Writing PL/SQL Programs in Oracle 12c

Na$ve  Object  Type  Evolu$on  Implemented  in  Oracle  Database  12c  

•  You  can  evolve  object  types  –  Changes  in  a  base  type  cascade  through  subtypes  –  This  means  you  can  easily  upgrade  

•  Persistent  object  types:  stand  alone  &  embedded  

–  Object  types  can  specialize  •  Object  types  •  Collec$on  types  •  Embedded  parameters  and  return  types  

•  You  can  convert  object  types  to  rela$onal  data  

Page 18: Writing PL/SQL Programs in Oracle 12c

Na$ve  Object  Type  Evolu$on  Example,  Part  #1  Adding  A_ribute  

SQL> CREATE OR REPLACE 2 TYPE base_t IS OBJECT 3 ( obj_id NUMBER ) 4 NOT FINAL; 5 /

SQL> ALTER TYPE base_t 2 ADD ATTRIBUTE ( obj_name VARCHAR2(30)) 3 CASCADE INCLUDING TABLE DATA;

SQL> SELECT base_t(1,'Hello World!') FROM dual;

•  Create  an  instance  of  the  evolved  object  type  

Page 19: Writing PL/SQL Programs in Oracle 12c

Na$ve  Object  Type  Evolu$on  Example,  Part  #2  Adding  Constructor  

SQL> ALTER TYPE base_t 2 ADD 3 CONSTRUCTOR FUNCTION base_t 4 ( obj_id NUMBER ) RETURN SELF AS RESULT 5 CASCADE INCLUDING TABLE DATA; 6 /

SQL> ALTER TYPE base_t 2 ADD 3 CONSTRUCTOR FUNCTION base_t 4 ( obj_id NUMBER 5 , obj_name VARCHAR2 ) RETURN SELF AS RESULT 6 CASCADE INCLUDING TABLE DATA; 7 /

Page 20: Writing PL/SQL Programs in Oracle 12c

Na$ve  Object  Type  Evolu$on  Example,  Part  #3  Adding  &  Dropping  Func$on  

SQL> ALTER TYPE base_t 2 ADD MEMBER FUNCTION to_string RETURN VARCHAR2 3 CASCADE INCLUDING TABLE DATA;

SQL> ALTER TYPE base_t 2 DROP CONSTRUCTOR FUNCTION base_t ( obj_id NUMBER ) 3 RETURN SELF AS RESULT 4 CASCADE INCLUDING TABLE DATA;

Page 21: Writing PL/SQL Programs in Oracle 12c

Na$ve  Object  Type  Evolu$on  Example,  Part  #4  Convert  to  Rela$onal  Set  

SQL> CREATE TABLE hobbit AS 2 SELECT * 3 FROM TABLE( 4 SELECT CAST( 5 COLLECT( 6 TREAT(log_object AS hobbit_t)) AS hobbit_c) 7 FROM log_base 8 WHERE log_object IS OF (hobbit_t)) t; ;

Page 22: Writing PL/SQL Programs in Oracle 12c

Iden$ty  Columns  Implemented  in  Oracle  Database  12c  

•  Iden$ty  Columns,  like  the  ANSI  specifica$on  –  Replaces  columns  where  sequences  where  used  –  Implements  an  implicit  sequence,  like  a  unique  constraint  implements  an  implicit  index  

–  Sequence  name  uses  a  system  generated  name  

Page 23: Writing PL/SQL Programs in Oracle 12c

Iden$ty  Columns  Implemented  in  Oracle  Database  12c  

•  Difficult  to  migrate  from  sequences  with  .NEXTVAL  and  .CURRVAL  pseudocolumns –  Changes  required  on  any  procedures  that  manage  transac$ons  with  surrogate  primary  and  foreign  keys  

–  The  RETURNING INTO  clause  becomes  defacto  future    

Page 24: Writing PL/SQL Programs in Oracle 12c

Iden$ty  Columns  Example,  Part  #1  in  Oracle  Database  12c  

SQL> CREATE TABLE identity 2 ( id NUMBER GENERATED ALWAYS AS IDENTITY 3 , text VARCHAR2(10) 4 CONSTRAINT identity_nn1 NOT NULL );

Page 25: Writing PL/SQL Programs in Oracle 12c

Iden$ty  Columns  Example,  Part  #2  in  Oracle  Database  12c  

SQL> CREATE TABLE unconstrained 2 ( unconstrained_id NUMBER GENERATED ALWAYS AS IDENTITY 3 , text VARCHAR2(10) 4 , CONSTRAINT unconstrained_pk 5 PRIMARY KEY(unconstrained_id));

SQL> CREATE TABLE constrained 2 ( constrained_id NUMBER GENERATED AS IDENTITY 3 , unconstrained_id NUMBER 4 , text VARCHAR2(10) 5 , CONSTRAINT constrained_fk 6 FOREIGN KEY (unconstrained_id) 7 REFERENCES unconstrained(unconstrained_id));

Page 26: Writing PL/SQL Programs in Oracle 12c

Iden$ty  Columns  Example,  Part  #3  in  Oracle  Database  12c  

SQL> VARIABLE seq_value NUMBER SQL> INSERT INTO unconstrained (text) VALUES ('One') 2 RETURNING unconstrained_id INTO :seq_value; SQL> INSERT INTO constrained (unconstrained_id, text) 2 VALUES (:seq_value,'One');

•  SQL*Plus  session  variable  seq_value •  The  RETURNING column_value INTO local_variable  syntax  captures  the  iden$ty  column  primary  key  value  for  reuse  as  a  foreign  key  value  

•  Using  the  local_variable  as  a  foreign  key  value  

Page 27: Writing PL/SQL Programs in Oracle 12c

Invisible  Columns  Implemented  in  Oracle  Database  12c  

•  They’re  there  but  not  there  •  They’re  not  there  when  you  describe  the  table  •  They’re  not  there  when  you  query  with  an  *  in  the  SELECT-

list  of  a  query  •  They’re  not  present  in  PL/SQL  when  you  anchor  against  a  table  

but  are  present  when  you  anchor  against  a  column  

Page 28: Writing PL/SQL Programs in Oracle 12c

Invisible  Columns  Implemented  in  Oracle  Database  12c  

•  They’re  not  in  the  old  views  –  CDB_,  ALL_,  DBA_,  or  USER_TAB_COLUMNS  

•  They’re  in  the  new  views  –  CDB_,  ALL_,  DBA_,  or  USER_TAB_COLS

Page 29: Writing PL/SQL Programs in Oracle 12c

Invisible  Columns  Example,  Part  #1  in  Oracle  Database  12c  

SQL> CREATE TABLE secret 2 ( secret_id NUMBER 3 CONSTRAINT secret_pk PRIMARY KEY 4 , description VARCHAR2(20) 5 , reality VARCHAR2(20) INVISIBLE); SQL> INSERT INTO secret

2 ( secret_id

3 , description

4 , reality ) 5 VALUES

6 (1,'One row.','Unknown');

Page 30: Writing PL/SQL Programs in Oracle 12c

Invisible  Columns  Example,  Part  #2  in  Oracle  Database  12c  

SQL> DECLARE 2 CURSOR c (cv_id NUMBER) IS

3 SELECT * FROM secret WHERE secret_id = cv_id; 4 lv_record c%ROWTYPE; 5 BEGIN

6 OPEN c (1);

7 FETCH c INTO lv_record;

8 dbms_output.put_line(lv_record.reality); 9 END; 10 /

The  hidden  column  isn’t  found  in  an  implicitly  constructed  cursor  

Page 31: Writing PL/SQL Programs in Oracle 12c

Invisible  Columns  Example,  Part  #3  in  Oracle  Database  12c  

dbms_output.put_line(lv_record.reality); *

ERROR at line 8:

ORA-06550: line 8, column 34:

PLS-00302: component 'REALITY' must be declared ORA-06550: line 8, column 3:

PL/SQL: Statement ignored

Page 32: Writing PL/SQL Programs in Oracle 12c

Invisible  Columns  Example,  Part  #4  in  Oracle  Database  12c  

SQL> DECLARE 2 CURSOR c (cv_id NUMBER) IS

3 SELECT secret_id 4 , description 5 , reality 6 FROM secret

7 WHERE secret_id = cv_id;

8 lv_record c%ROWTYPE;

9 BEGIN 10 OPEN c (1);

11 FETCH c INTO lv_record;

12 dbms_output.put_line(lv_record.reality); 13 END;

14 /

The  SELECT-­‐list  must  be  explicit  and  include  any  

hidden  column  

Page 33: Writing PL/SQL Programs in Oracle 12c

UTL_CALL_STACK  Package  Implementa$on  Example  

SQL> CREATE OR REPLACE PROCEDURE pear IS 2 /* Declare two variables. */ 3 lv_one_character VARCHAR2(1); 4 lv_two_character VARCHAR2(2) := 'AB'; 5 BEGIN 6 lv_one_character := lv_two_character; 7 END pear; 8 /

SQL> CREATE OR REPLACE PROCEDURE orange IS 2 BEGIN 3 pear(); 4 END orange; 5 /

Page 34: Writing PL/SQL Programs in Oracle 12c

UTL_CALL_STACK  Package  Implementa$on  Example  (con$nued)  

SQL> CREATE OR REPLACE PROCEDURE apple IS 2 BEGIN 3 orange(); 4 END apple; 5 /

•  The  APPLE  procedure  calls  the  ORANGE  procedure  •  The  ORANGE  procedure  calls  the  PEAR  procedure  •  The  PEAR  procedure  generates  and  error  

Page 35: Writing PL/SQL Programs in Oracle 12c

UTL_CALL_STACK  Package  Implemented  in  Oracle  12c  –  UTL_CALL_STACK

SQL> BEGIN 2 apple; 3 EXCEPTION 4 WHEN others THEN ... 27 END; 28 /

Page 36: Writing PL/SQL Programs in Oracle 12c

UTL_CALL_STACK  Package  Implemented  of  UTL_CALL_STACK  

SQL> BEGIN ... 5 FOR i IN REVERSE 1..utl_call_stack.backtrace_depth LOOP 6 /* Check for an anonymous block. */ 7 IF utl_call_stack.backtrace_unit(i) IS NULL THEN 8 /* No utl_call_stack automatic error. */ 9 dbms_output.put_line( 10 'ORA-06512: at Anonymous Block, line ’ 11 ||utl_call_stack.backtrace_line(i)); 12 ELSE 13 /* No utl_call_stack automatic error. */ 14 dbms_output.put_line( 15 'ORA-06512: at ’ 16 ||utl_call_stack.backtrace_unit(i) 17 ||', line '||utl_call_stack.backtrace_line(i)); 18 END IF; ... 27 END; 28 /

Page 37: Writing PL/SQL Programs in Oracle 12c

UTL_CALL_STACK  Package  Implemented  of  UTL_CALL_STACK  (con$nued)  

SQL> BEGIN ... 19 /* The backtrace and error depth are unrelated. The 20 call depth can be higher than the error depth. */ 21 IF i = utl_call_stack.error_depth THEN 22 dbms_output.put_line( 23 'ORA-'||LPAD(utl_call_stack.error_number(i),5,0) 24 ||' '||utl_call_stack.error_msg(i)); 25 END IF; 26 END LOOP; 27 END; 28 /

Page 38: Writing PL/SQL Programs in Oracle 12c

Top’N  Query  Implemented  in  Oracle  Database  12c  

•  You  can  define  a  Top’n  query  with  or  without  an  offset  •  You    can  make  the  statement  dynamic  when  you  

•  Call  it  from  an  NDS  statement  •  Call  it  from  an  external  program  

h_p://blog.mclaughlinsodware.com/2014/01/01/oracle-­‐12c-­‐offset-­‐rows/  

Page 39: Writing PL/SQL Programs in Oracle 12c

Review  

•  Cache  invoker  rights  func$ons  •  White  lis$ng  callers  –  Func$ons  –  Procedures  –  Packages  –  Object  types  

•  WITH  clause  PL/SQL  func$ons  •  Use  PL/SQL  types  in  SQL  statements  

Page 40: Writing PL/SQL Programs in Oracle 12c

Review  (con$nued)  

•  Oracle  type  evolu$on  –  Discoverying  type  dependencies  –  Cascading  type  changes  

•  Using  iden$ty  columns  in  transac$ons  •  Working  with  invisible  columns  •  UTL_CALL_STACK  Package  •  Top’n  Queries  

Page 41: Writing PL/SQL Programs in Oracle 12c

Ques$ons  &  Answers