Upload
buituyen
View
319
Download
6
Embed Size (px)
Citation preview
Wri$ng PL/SQL Programs in Oracle 12c
By Michael McLaughlin
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
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
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
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
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
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 /
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 /
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
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
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 /
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
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
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');
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 /
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
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
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
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 /
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;
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; ;
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
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
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 );
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));
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
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
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
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');
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
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
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
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 /
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
UTL_CALL_STACK Package Implemented in Oracle 12c – UTL_CALL_STACK
SQL> BEGIN 2 apple; 3 EXCEPTION 4 WHEN others THEN ... 27 END; 28 /
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 /
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 /
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/
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
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
Ques$ons & Answers