SlideShare a Scribd company logo
1 Copyright © 2011, Oracle and/or its affiliates. All rights
reserved.
Insert Information Protection Policy Classification from Slide 8
2 Copyright © 2011, Oracle and/or its affiliates. All rights
reserved.
Insert Information Protection Policy Classification from Slide 8
Five things you probably
didn’t know about PL/SQL
Thomas Kyte
http://asktom.oracle.com/
3
Who am I
• Been with Oracle since 1993
• User of Oracle since 1987
• The “Tom” behind AskTom in
Oracle Magazine
www.oracle.com/oramag
• Expert Oracle Database
Architecture
• Effective Oracle by Design
• Expert One on One Oracle
• Beginning Oracle
4
<Insert Picture Here>
Five things you probably didn’t know about
PL/SQL
• Trigger Trickery
• Why you need to ignore errors (really)
• Elaboration Code
• Implicit conversions are beyond evil
• What About Roles…
5
Trigger
Trickery
6
<Insert Picture Here>
Trigger Trickery
• When do your triggers actually fire?
• What do your triggers actually see?
• How many times can a row level trigger fire?
• Will your trigger actually fire?
• Does your trigger prevent things from happening
as you think they should?
7
<Insert Picture Here>
Trigger Trickery
• When do your triggers actually fire?
• What do your triggers actually see?
– Before trigger sees ‘nothing’
– Before for each row trigger sees what the row might look like
(consistent read) and what that row might become (based on
consistent read
– After trigger sees the row as it was before and after the row
update. This may or may not be what the row looks like after the
modification is done! (because of what is coming)
– After trigger sees ‘nothing’
8
<Insert Picture Here>
Trigger Trickery
• How many times can a trigger fire?
– Before – twice
– Before, for each row – twice per row
– After, for each row – twice per row (except for the last
row to be updated – it can only fire once ;) )
– After - once
9
Trigger Trickery
ops$tkyte%ORA11GR2> create table t ( x int, y int );
Table created.
ops$tkyte%ORA11GR2> insert into t values ( 1, 0 );
1 row created.
ops$tkyte%ORA11GR2> insert into t values ( 2, 0 );
1 row created.
ops$tkyte%ORA11GR2> insert into t values ( 3, 0 );
1 row created.
10
Trigger Trickery
ops$tkyte%ORA11GR2> create or replace trigger t_bu
2 before update on t
3 begin
4 dbms_output.put_line
5 ( 'I am the before trigger firing' );
6 end;
7 /
Trigger created.
11
Trigger Trickery
ops$tkyte%ORA11GR2> create or replace trigger t_bufer
2 before update on t for each row
3 begin
4 dbms_output.put_line
5 ( 'BUFER: changing ' ||
6 :old.x || ', ' || :old.y ||
7 ' to ' || :new.x || ', ' || :new.y );
8 end;
9 /
Trigger created.
12
Trigger Trickery
ops$tkyte%ORA11GR2> create or replace trigger t_aufer
2 after update on t for each row
3 begin
4 dbms_output.put_line
5 ( 'AUFER: changed ' ||
6 :old.x || ', ' || :old.y ||
7 ' to ' || :new.x || ', ' || :new.y );
8 end;
9 /
Trigger created.
13
Trigger Trickery
ops$tkyte%ORA11GR2> create or replace trigger t_au
2 after update on t
3 begin
4 dbms_output.put_line
5 ( 'I am the after trigger firing' );
6 end;
7 /
Trigger created.
14
Trigger Trickery
Session 1> update t set y = 100 where x = 3;
I am the before trigger firing
BUFER: changing 3, 0 to 3, 100
AUFER: changed 3, 0 to 3, 100
I am the after trigger firing
1 row updated.
NOTE: no commit!
15
Trigger Trickery
Session 2> update t set y = 42;
NOTE: this is a second session, this blocks of course
since the first session has row ‘3’ locked already.
16
Trigger Trickery
Session 1> commit;
Commit complete.
NOTE: this is the first session, the one blocking the
second session
17
Trigger Trickery
Session 2> update t set y = 42;
I am the before trigger firing
BUFER: changing 1, 0 to 1, 42
AUFER: changed 1, 0 to 1, 42
BUFER: changing 2, 0 to 2, 42
AUFER: changed 2, 0 to 2, 42
BUFER: changing 3, 0 to 3, 42 <= <= how did that happen?
I am the before trigger firing
BUFER: changing 1, 0 to 1, 42
AUFER: changed 1, 0 to 1, 42
BUFER: changing 2, 0 to 2, 42
AUFER: changed 2, 0 to 2, 42
BUFER: changing 3, 100 to 3, 42
AUFER: changed 3, 100 to 3, 42
I am the after trigger firing
3 rows updated.
18
<Insert Picture Here>
Trigger Trickery
• So, what does that mean?
– Never do anything non-transactional in a trigger
– Pragma autonomous_transaction is a really bad idea
in general
– UTL_ packages – really bad idea. They do not roll
back (utl_file, utl_http, utl_smtp, etc etc etc)
– Even just setting global variables in a trigger can be
tricky
19
<Insert Picture Here>
Trigger Trickery
• Will your trigger actually fire?
– No, not always
• Does your trigger prevent things from happening
as you think they should?
– Yes, sometimes
20
Trigger Trickery
ops$tkyte%ORA11GR2> create table t ( x int, y int );
Table created.
ops$tkyte%ORA11GR2> create or replace trigger t
2 before insert on t for each row
3 begin
4 :new.y := -:new.x;
5 end;
6 /
Trigger created.
21
Trigger Trickery
ops$tkyte%ORA11GR2> insert into t ( x, y ) values ( 100, 200 );
1 row created.
ops$tkyte%ORA11GR2> select * from t;
X Y
---------- ----------
100 -100
ops$tkyte%ORA11GR2> commit;
22
Trigger Trickery
ops$tkyte%ORA11GR2> !cat t.ctl
LOAD DATA
INFILE *
INTO TABLE t
REPLACE
FIELDS TERMINATED BY '|' ( x ,y )
BEGINDATA
100|42
23
Trigger Trickery
ops$tkyte%ORA11GR2> !sqlldr / t direct=y
SQL*Loader: Release 11.2.0.2.0 - Production on Tue Oct 4
13:13:49 2011
Copyright (c) 1982, 2009, Oracle and/or its affiliates.
All rights reserved.
Load completed - logical record count 1.
24
Trigger Trickery
ops$tkyte%ORA11GR2> select * from t;
X Y
---------- ----------
100 42 <<== that is wrong?
25
Trigger Trickery
ops$tkyte%ORA11GR2> truncate table t;
Table truncated.
ops$tkyte%ORA11GR2> insert /*+ append */ into t select
100, 200 from dual;
1 row created.
ops$tkyte%ORA11GR2> select * from t;
X Y
---------- ----------
100 -100
The fact we can select from that table tells us direct
pathing did not happen
26
Trigger Trickery
ops$tkyte%ORA11GR2> drop trigger t;
Trigger dropped.
ops$tkyte%ORA11GR2> truncate table t;
Table truncated.
ops$tkyte%ORA11GR2> insert /*+ append */ into t select
100, 200 from dual;
1 row created.
27
Trigger Trickery
ops$tkyte%ORA11GR2> select * from t;
select * from t
*
ERROR at line 1:
ORA-12838: cannot read/modify an object after modifying
it in parallel
That is what you expect after a direct path insert!
Triggers prevent it.
28
Why you want to
ignore errors
(really)
29
<Insert Picture Here>
Please do ignore errors (really)
• In my experience, error handling is done wrong
more often than it is done right
• You don’t want to catch all exceptions
• You want to catch specific exceptions you are
expecting (which means they aren’t exceptions)
• You should ignore all others – or of you do catch
them to clean up a resource, RE-RAISE them
30
Please do ignore errors (really)
Begin p; end;
Is really executed from a client as if it were:
Begin
savepoint X;
p;
Exception
When others then
rollback to X;
RAISE;
End;
31
Please do ignore errors (really)
ops$tkyte%ORA11GR2> create table t ( x int check (x>0) );
Table created.
32
Please do ignore errors (really)
ops$tkyte%ORA11GR2> create or replace procedure noexceptions
2 as
3 begin
4 insert into t values ( 1 );
5 insert into t values ( 0 );
6 end;
7 /
Procedure created.
33
Please do ignore errors (really)
ops$tkyte%ORA11GR2> create or replace procedure exceptions
2 as
3 begin
4 insert into t values ( 1 );
5 insert into t values ( 0 );
6 exception
7 when others
8 then
9 dbms_output.put_line( 'Error!!! ' || sqlerrm );
10 end;
11 /
Procedure created.
34
Please do ignore errors (really)
ops$tkyte%ORA11GR2> exec noexceptions;
BEGIN noexceptions; END;
*
ERROR at line 1:
ORA-02290: check constraint (OPS$TKYTE.SYS_C0022770) violated
ORA-06512: at "OPS$TKYTE.NOEXCEPTIONS", line 5
ORA-06512: at line 1
ops$tkyte%ORA11GR2> select * from t;
no rows selected
35
Please do ignore errors (really)
ops$tkyte%ORA11GR2> exec exceptions
Error!!! ORA-02290: check constraint (OPS$TKYTE.SYS_C0022770)
violated
PL/SQL procedure successfully completed.
ops$tkyte%ORA11GR2> select * from t;
X
----------
1
36
Please do ignore errors (really)
It is ok to catch exceptions you are EXPECTING
Begin
…
begin
select x into y from t where …;
exception
when no_data_found then
y := 42;
end;
…
37
Please do ignore errors (really)
It is ok to catch exceptions at the TOP-LEVEL to log/change them. But
re-raise them!
Begin
p;
Exception
When others then
new_error_message :=
log_error_using_autonomous_transaction;
raise_application_error( -20001, new_error_message );
End;
38
<Insert Picture Here>
Please do ignore errors (really)
• This is the #1 cause of bugs that I see time and
time again
• Do not catch exceptions at lower levels of code
(most – 99.99999999% of code – should not have a
when others)
• Do catch it at the highest level to log it, or to make it
“user friendly”
• When others not followed by
raise/raise_application_error should be a RED flag
39
Please do ignore errors (really)
ops$tkyte%ORA11GR2> alter procedure bad_code compile
2 PLSQL_Warnings = 'enable:all'
3 reuse settings
4 /
SP2-0805: Procedure altered with compilation warnings
ops$tkyte%ORA11GR2> show errors procedure bad_code
Errors for PROCEDURE BAD_CODE:
LINE/COL ERROR
-------- ---------------------------------------------------------------
--
1/1 PLW-05018: unit BAD_CODE omitted optional AUTHID clause;
default value DEFINER used
9/8 PLW-06009: procedure "BAD_CODE" OTHERS handler does not end in
RAISE or RAISE_APPLICATION_ERROR
40
Elaboration Code
41
<Insert Picture Here>
Elaboration Code
• Did you know that you can have some code run
when a package is first ‘touched’
• Perform a one time setup operation
• Without having to call an “init” routine, set a flag,
etc
42
Elaboration Code
ops$tkyte%ORA11GR2> create or replace package my_package
2 as
3 procedure p;
4 end;
5 /
Package created.
43
Elaboration Code
ops$tkyte%ORA11GR2> create or replace package body my_package
2 as
3 g_some_global varchar2(30);
4
5 procedure p
6 is
7 begin
8 dbms_output.put_line( g_some_global );
9 end;
10
11
12
13 begin
14 g_some_global := 'result of some logic';
15 end;
16 /
Package body created.
44
Elaboration Code
ops$tkyte%ORA11GR2> exec my_package.p
result of some logic
PL/SQL procedure successfully completed.
45
<Insert Picture Here>
Elaboration Code
• One time initialization
– DBMS_LDAP callout for example
13 begin
14 g_some_global := dbms_ldap…;
15 end;
16 /
– Load a lookup table
– Any sort of complex initialization that cannot be done
in a declare block
46
Implicit
conversions are
evil
47
<Insert Picture Here>
Implicit conversions are evil
• SQL/PLSQL are too ‘user friendly’ – unlike C
which complained about everything
• Implicit conversions of strings to numbers, strings
to dates, raw to string, etc are probably the #2
cause of bugs I see time and time again
• Even worse are the implicit conversions that rely
on default NLS settings!
48
Implicit conversions are evil
ops$tkyte%ORA11GR2> create or replace procedure inj( p_date in date )
2 as
3 l_rec all_users%rowtype;
4 c sys_refcursor;
5 l_query long;
6 begin
7 l_query := '
8 select *
9 from all_users
10 where created = ''' ||p_date ||''''; -- DOUBLE implicit conversion!
11
12 dbms_output.put_line( l_query );
13 open c for l_query;
14
15 for i in 1 .. 5
16 loop
17 fetch c into l_rec;
18 exit when c%notfound;
19 dbms_output.put_line( l_rec.username || '.....' );
20 end loop;
…
49
Implicit conversions are evil
7 l_query := '
8 select *
9 from all_users
10 where created = ''' ||p_date ||'''';
Creates a query that is semantically equivalent to:
Where created = to_date( to_char( date-field ) );
Two implicit conversions – both of which rely on the NLS_DATE
settings!
50
Implicit conversions are evil
ops$tkyte%ORA11GR2> exec inj( sysdate )
select *
from all_users
where created = '04-OCT-11'
PL/SQL procedure successfully completed.
51
Implicit conversions are evil
ops$tkyte%ORA11GR2> alter session set
2 nls_date_format = 'dd-mon-yyyy"'' or ''a'' = ''a"';
Session altered.
52
Implicit conversions are evil
ops$tkyte%ORA11GR2> exec inj( sysdate )
select *
from all_users
where created = '04-oct-2011' or 'a' = 'a'
A.....
EBRAPP.....
EBRTBLS.....
UTIL.....
USER2.....
PL/SQL procedure successfully completed.
53
Implicit conversions are evil
ops$tkyte%ORA11GR2> alter session set
2 nls_date_format = '"''union select tname,0,null from tab--"';
Session altered.
Select *
from all_users
where created = ''union select tname,0,null from tab--'
54
<Insert Picture Here>
Implicit conversions are evil
• What about performance?
– Repeated conversions
– Access path reductions
– Partition elimination eliminated
55
Implicit conversions are evil
ops$tkyte%ORA11GR2> declare
2 l_date varchar2(30) := '01-jan-2011';
3 l_start number;
4 begin
5 l_start := dbms_utility.get_cpu_time;
6
7 for i in 1 .. 10
8 loop
9 for x in ( select *
10 from big_table.big_table
11 where created = l_date )
12 loop
13 null;
14 end loop;
15 end loop;
16
17 dbms_output.put_line( 'CPU: ' ||
18 to_char( dbms_utility.get_cpu_time-l_start ) );
19 end;
20 /
CPU: 132
56
Implicit conversions are evil
ops$tkyte%ORA11GR2> declare
2 l_date date := to_date( '01-jan-2011', 'dd-mon-yyyy' );
3 l_start number;
4 begin
5 l_start := dbms_utility.get_cpu_time;
6
7 for i in 1 .. 10
8 loop
9 for x in ( select *
10 from big_table.big_table
11 where created = l_date )
12 loop
13 null;
14 end loop;
15 end loop;
16
17 dbms_output.put_line( 'CPU: ' ||
18 to_char( dbms_utility.get_cpu_time-l_start ) );
19 end;
20 /
CPU: 94 30% less CPU in this case
57
Implicit conversions are evil
ops$tkyte%ORA11GR2> create table t
2 ( x varchar2(20) constraint t_pk primary key,
3 y varchar2(30)
4 );
Table created.
ops$tkyte%ORA11GR2> insert into t
2 select user_id, username
3 from all_users;
47 rows created.
ops$tkyte%ORA11GR2> commit;
Commit complete.
58
Implicit conversions are evil
ops$tkyte%ORA11GR2> declare
2 l_rec t%rowtype;
3 l_key number := 5;
4 begin
5 select * into l_rec from t where x = l_key;
6
7 for x in (select plan_table_output
8 from TABLE( dbms_xplan.display_cursor() ) )
9 loop
10 dbms_output.put_line( x.plan_table_output );
11 end loop;
12 end;
13 /
59
Implicit conversions are evil
SQL_ID 18796jgha0hwz, child number 0
-------------------------------------
SELECT * FROM T WHERE X = :B1
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 3 (100)| |
|* 1 | TABLE ACCESS FULL| T | 1 | 29 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(TO_NUMBER("X")=:B1)
60
Implicit conversions are evil
ops$tkyte%ORA11GR2> declare
2 l_rec t%rowtype;
3 l_key varchar2(20) := '5';
4 begin
5 select * into l_rec from t where x = l_key;
6
7 for x in (select plan_table_output
8 from TABLE( dbms_xplan.display_cursor() ) )
9 loop
10 dbms_output.put_line( '.'||x.plan_table_output );
11 end loop;
12 end;
13 /
61
Implicit conversions are evil
SQL_ID 18796jgha0hwz, child number 1
-------------------------------------
SELECT * FROM T WHERE X = :B1
Plan hash value: 1303508680
------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 1 (100)| |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 29 | 1 (0)| 00:00:01 |
|* 2 | INDEX UNIQUE SCAN | T_PK | 1 | | 1 (0)| 00:00:01 |
------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("X"=:B1)
62
Implicit conversions are evil
ops$tkyte%ORA11GR2> CREATE TABLE t
2 (
3 dt date,
4 x int,
5 y varchar2(30)
6 )
7 PARTITION BY RANGE (dt)
8 (
9 PARTITION part1 VALUES LESS THAN(to_date('31-jan-2011', 'dd-mon-yyyy')),
10 PARTITION part2 VALUES LESS THAN(to_date('28-feb-2011', 'dd-mon-yyyy'))
11 )
12 /
Table created.
63
Implicit conversions are evil
ops$tkyte%ORA11GR2> declare
2 l_date timestamp := timestamp'2011-01-15 00:00:00.000';
3 l_count number;
4 begin
5 select count(*) into l_count from t where dt = l_date;
6
7 for x in (select plan_table_output
8 from TABLE( dbms_xplan.display_cursor() ) )
9 loop
10 dbms_output.put_line( '.'||x.plan_table_output );
11 end loop;
12 end;
13 /
64
Implicit conversions are evil
SQL_ID 0t5m83d3m67q7, child number 0
-------------------------------------
SELECT COUNT(*) FROM T WHERE DT = :B1
Plan hash value: 3225603066
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 2 (100)| | | |
| 1 | SORT AGGREGATE | | 1 | 9 | | | | |
| 2 | PARTITION RANGE ALL| | 1 | 9 | 2 (0)| 00:00:01 | 1 | 2 |
|* 3 | TABLE ACCESS FULL | T | 1 | 9 | 2 (0)| 00:00:01 | 1 | 2 |
---------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - filter(INTERNAL_FUNCTION("DT")=:B1)
65
Implicit conversions are evil
ops$tkyte%ORA11GR2> declare
2 l_date date := to_date( '15-jan-2011', 'dd-mon-yyyy' );
3 l_count number;
4 begin
5 select count(*) into l_count from t where dt = l_date;
6
7 for x in (select plan_table_output
8 from TABLE( dbms_xplan.display_cursor() ) )
9 loop
10 dbms_output.put_line( '.'||x.plan_table_output );
11 end loop;
12 end;
13 /
66
Implicit conversions are evil
.SQL_ID 0t5m83d3m67q7, child number 1
.-------------------------------------
.SELECT COUNT(*) FROM T WHERE DT = :B1
.
.Plan hash value: 3660200434
.
.------------------------------------------------------------------------------------------------
.| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
.------------------------------------------------------------------------------------------------
.| 0 | SELECT STATEMENT | | | | 2 (100)| | | |
.| 1 | SORT AGGREGATE | | 1 | 9 | | | | |
.| 2 | PARTITION RANGE SINGLE| | 1 | 9 | 2 (0)| 00:00:01 | KEY | KEY |
.|* 3 | TABLE ACCESS FULL | T | 1 | 9 | 2 (0)| 00:00:01 | KEY | KEY |
.------------------------------------------------------------------------------------------------
.
.Predicate Information (identified by operation id):
.---------------------------------------------------
.
. 3 - filter("DT"=:B1)
67
<Insert Picture Here>
Implicit conversions are evil
• Lots and lots of bugs
– What is ‘01/02/03’?
– where column = to_char(sysdate) – what does that
mean?
68
What about
Roles?
69
<Insert Picture Here>
PL/SQL and roles
• Quote:
– To create without errors (to compile the subprogram or
package successfully) requires these additional
privileges: The owner of the subprogram or package
must be explicitly granted the necessary object
privileges for all objects referenced within the body of
the code.
– The owner cannot obtain required privileges
through roles.
Note by me: Not entirely true, but almost always true
70
<Insert Picture Here>
PL/SQL and roles
• Why is this the case?
– Roles are for the hundreds/thousands of application users.
You have very few application schemas that need to have
compiled stored objects
– Direct GRANTS make monitoring the set of privileges a
schema needs infinitely easier than a massive hierarchy of
roles (least privilege)
– What should the effect of non-default, password protected,
application enabled roles?
71
<Insert Picture Here>
PL/SQL and roles – Two Modes
• Definers Rights
– Default method for stored compiled code
– All code is compiled with base (no roles) privileges
granted directly to the owner of the procedure.
72
<Insert Picture Here>
PL/SQL and roles – Two Modes
• Invokers Rights
– Default method for anonymous blocks
– Using authid current_user – All code is compiled with base
privileges granted directly to the owner of the procedure. Nothing
changes there – owner still needs direct access.
– SQL rights are re-evaluated at runtime using the current set of
privileges in place in the current session running the code.
• Tables accessed at runtime might be different than tables
checked against at compile time.
– PL/SQL bindings are fixed at compile time.
73 Copyright © 2011, Oracle and/or its affiliates. All rights
reserved.
Insert Information Protection Policy Classification from Slide 8
ops$tkyte%ORA11GR2> create table t
2 as
3 select *
4 from all_users
5 where rownum <= 3;
Table created.
PL/SQL and roles – Two Modes
74 Copyright © 2011, Oracle and/or its affiliates. All rights
reserved.
Insert Information Protection Policy Classification from Slide 8
ops$tkyte%ORA11GR2> create or replace procedure show_user_info_ir
2 AUTHID CURRENT_USER
3 as
4 begin
5 dbms_output.put_line( '--------- IR Status ---------' );
6 for x in (select sys_context('userenv', 'authenticated_identity' ) ai,
7 sys_context('userenv', 'current_schema') cs,
8 sys_context('userenv', 'current_schemaid') cs_id,
9 sys_context('userenv', 'current_user') cu
10 from dual )
11 loop
12 dbms_output.put_line( 'authenticated identity: ' || x.ai );
13 dbms_output.put_line( 'current schema : ' || x.cs );
14 dbms_output.put_line( 'current schemaid : ' || x.cs_id );
15 dbms_output.put_line( 'current user : ' || x.cu );
16 end loop;
17 end;
18 /
Procedure created.
PL/SQL and roles – Two Modes
75 Copyright © 2011, Oracle and/or its affiliates. All rights
reserved.
Insert Information Protection Policy Classification from Slide 8
ops$tkyte%ORA11GR2> create or replace procedure show_user_info_dr
2 AUTHID DEFINER
3 as
4 begin
5 dbms_output.put_line( '--------- DR Status ---------' );
6 for x in (select sys_context('userenv', 'authenticated_identity' ) ai,
7 sys_context('userenv', 'current_schema') cs,
8 sys_context('userenv', 'current_schemaid') cs_id,
9 sys_context('userenv', 'current_user') cu
10 from dual )
11 loop
12 dbms_output.put_line( 'authenticated identity: ' || x.ai );
13 dbms_output.put_line( 'current schema : ' || x.cs );
14 dbms_output.put_line( 'current schemaid : ' || x.cs_id );
15 dbms_output.put_line( 'current user : ' || x.cu );
16 end loop;
17 end;
18 /
Procedure created.
PL/SQL and roles – Two Modes
76 Copyright © 2011, Oracle and/or its affiliates. All rights
reserved.
Insert Information Protection Policy Classification from Slide 8
ops$tkyte%ORA11GR2> create or replace procedure curr_user
2 AUTHID CURRENT_USER
3 as
4 begin
5 show_user_info_ir;
6 show_user_info_dr;
7 dbms_output.put_line( '--------- data ---------' );
8 for x in (select * from t)
9 loop
10 dbms_output.put_line( x.username );
11 end loop;
12 for x in (select * from ops$tkyte.t)
13 loop
14 dbms_output.put_line( x.username );
15 end loop;
16 end;
17 /
Procedure created.
PL/SQL and roles – Two Modes
Bound at compile
time
Checked with base
privileges at compile
time, re-bound at
runtime
77 Copyright © 2011, Oracle and/or its affiliates. All rights
reserved.
Insert Information Protection Policy Classification from Slide 8
ops$tkyte%ORA11GR2> grant execute on curr_user to public;
Grant succeeded.
No other grants, not on OPS$TKYTE.T, not on show_user_info_*
PL/SQL and roles – Two Modes
78 Copyright © 2011, Oracle and/or its affiliates. All rights
reserved.
Insert Information Protection Policy Classification from Slide 8
ops$tkyte%ORA11GR2> exec curr_user
--------- IR Status ---------
authenticated identity: tkyte
current schema : OPS$TKYTE
current schemaid : 274
current user : OPS$TKYTE
--------- DR Status ---------
authenticated identity: tkyte
current schema : OPS$TKYTE
current schemaid : 274
current user : OPS$TKYTE
--------- data ---------
SYS
SYSTEM
OUTLN
SYS
SYSTEM
OUTLN
PL/SQL and roles – Two Modes
79 Copyright © 2011, Oracle and/or its affiliates. All rights
reserved.
Insert Information Protection Policy Classification from Slide 8
ops$tkyte%ORA11GR2> connect scott/tiger
Connected.
PL/SQL and roles – Two Modes
80 Copyright © 2011, Oracle and/or its affiliates. All rights
reserved.
Insert Information Protection Policy Classification from Slide 8
scott%ORA11GR2> exec ops$tkyte.curr_user
--------- IR Status ---------
authenticated identity: scott
current schema : SCOTT
current schemaid : 83
current user : SCOTT
--------- DR Status ---------
authenticated identity: scott
current schema : OPS$TKYTE
current schemaid : 274
current user : OPS$TKYTE
--------- data ---------
BEGIN ops$tkyte.curr_user; END;
*
ERROR at line 1:
ORA-00942: table or view does not exist
ORA-06512: at "OPS$TKYTE.CURR_USER", line 8
ORA-06512: at line 1
PL/SQL and roles – Two Modes
81 Copyright © 2011, Oracle and/or its affiliates. All rights
reserved.
Insert Information Protection Policy Classification from Slide 8
scott%ORA11GR2> create table t ( x int );
Table created.
PL/SQL and roles – Two Modes
82 Copyright © 2011, Oracle and/or its affiliates. All rights
reserved.
Insert Information Protection Policy Classification from Slide 8
scott%ORA11GR2> exec ops$tkyte.curr_user
--------- IR Status ---------
authenticated identity: scott
current schema : SCOTT
current schemaid : 83
current user : SCOTT
--------- DR Status ---------
authenticated identity: scott
current schema : OPS$TKYTE
current schemaid : 274
current user : OPS$TKYTE
--------- data ---------
BEGIN ops$tkyte.curr_user; END;
*
ERROR at line 1:
ORA-01007: variable not in select list
ORA-06512: at "OPS$TKYTE.CURR_USER", line 8
ORA-06512: at line 1
PL/SQL and roles – Two Modes
83 Copyright © 2011, Oracle and/or its affiliates. All rights
reserved.
Insert Information Protection Policy Classification from Slide 8
scott%ORA11GR2> create table t ( x int, y int, z int );
Table created.
PL/SQL and roles – Two Modes
84 Copyright © 2011, Oracle and/or its affiliates. All rights
reserved.
Insert Information Protection Policy Classification from Slide 8
scott%ORA11GR2> exec ops$tkyte.curr_user
--------- IR Status ---------
authenticated identity: scott
current schema : SCOTT
current schemaid : 83
current user : SCOTT
--------- DR Status ---------
authenticated identity: scott
current schema : OPS$TKYTE
current schemaid : 274
current user : OPS$TKYTE
--------- data ---------
BEGIN ops$tkyte.curr_user; END;
*
ERROR at line 1:
ORA-00932: inconsistent datatypes: expected DATE got NUMBER
ORA-06512: at "OPS$TKYTE.CURR_USER", line 8
ORA-06512: at line 1
PL/SQL and roles – Two Modes
85 Copyright © 2011, Oracle and/or its affiliates. All rights
reserved.
Insert Information Protection Policy Classification from Slide 8
scott%ORA11GR2> create table t
( x varchar2(30), y number, z date );
Table created.
scott%ORA11GR2> insert into t values
( 'hello', 0, sysdate );
1 row created.
PL/SQL and roles – Two Modes
86 Copyright © 2011, Oracle and/or its affiliates. All rights
reserved.
Insert Information Protection Policy Classification from Slide 8
scott%ORA11GR2> exec ops$tkyte.curr_user
--------- IR Status ---------
authenticated identity: scott
current schema : SCOTT
current schemaid : 83
current user : SCOTT
--------- DR Status ---------
authenticated identity: scott
current schema : OPS$TKYTE
current schemaid : 274
current user : OPS$TKYTE
--------- data ---------
hello
BEGIN ops$tkyte.curr_user; END;
*
ERROR at line 1:
ORA-00942: table or view does not exist
ORA-06512: at "OPS$TKYTE.CURR_USER", line 12
ORA-06512: at line 1
PL/SQL and roles – Two Modes
87 Copyright © 2011, Oracle and/or its affiliates. All rights
reserved.
Insert Information Protection Policy Classification from Slide 8
scott%ORA11GR2> connect /
Connected.
ops$tkyte%ORA11GR2> create or replace procedure curr_user
2 AUTHID CURRENT_USER
3 as
4 begin
5 show_user_info_ir;
6 show_user_info_dr;
7 dbms_output.put_line( '--------- data ---------' );
8 for x in (select username, user_id, created from t)
9 loop
10 dbms_output.put_line( x.username );
11 end loop;
12 end;
13 /
Procedure created.
PL/SQL and roles – Two Modes
88 Copyright © 2011, Oracle and/or its affiliates. All rights
reserved.
Insert Information Protection Policy Classification from Slide 8
ops$tkyte%ORA11GR2> connect scott/tiger
Connected.
PL/SQL and roles – Two Modes
89 Copyright © 2011, Oracle and/or its affiliates. All rights
reserved.
Insert Information Protection Policy Classification from Slide 8
scott%ORA11GR2> exec ops$tkyte.curr_user
--------- IR Status ---------
authenticated identity: scott
current schema : SCOTT
current schemaid : 83
current user : SCOTT
--------- DR Status ---------
authenticated identity: scott
current schema : OPS$TKYTE
current schemaid : 274
current user : OPS$TKYTE
--------- data ---------
BEGIN ops$tkyte.curr_user; END;
*
ERROR at line 1:
ORA-00904: "CREATED": invalid identifier
ORA-06512: at "OPS$TKYTE.CURR_USER", line 8
ORA-06512: at line 1
PL/SQL and roles – Two Modes
90
<Insert Picture Here>
PL/SQL and roles – Two Modes
• Definers Rights comes first, it is the default, it should be
the default. It is correct 99.99999999% of the time
• Invokers Rights are good for
– Routines that need to run “as caller”. Running as the owner
would/could cause security issues (think SYS owned code)
– It is infrequently executed or doesn’t use SQL
– It uses dynamic SQL (typically). It is not bound to a fixed set
of tables. It is a utility
• DUMP_CSV()
• PRINT_TABLE()
91
<Insert Picture Here>
PL/SQL and roles – Two Modes
• Invokers Rights will
– Lose the dependency mechanism
• They typically use dynamic SQL and even static is dynamic!
– Reduce the reliability of the stored code
• No compile time security checks for SQL really, short of the owner!
• Everything good about static SQL is lost typically
– Since SQL object references are not known until runtime and could be
different for everyone, you could flood the shared pool
– It is harder to develop and debug
92
<Insert Picture Here>
PL/SQL and roles – Two Modes
• In my opinion
– The loss of roles is not an issue for stored procedures
– You want the concept of LEAST PRIVILEGE
– You want the ability to see exactly what an application
schema can and cannot do
– The ambiguity presented by non-default roles, etc is gone
– The performance hit we would necessarily take is removed
– Invokers rights should be used very sparingly
93 Copyright © 2011, Oracle and/or its affiliates. All rights
reserved.
Insert Information Protection Policy Classification from Slide 8
Q&A
94 Copyright © 2011, Oracle and/or its affiliates. All rights
reserved.
Insert Information Protection Policy Classification from Slide 8
95 Copyright © 2011, Oracle and/or its affiliates. All rights
reserved.
Insert Information Protection Policy Classification from Slide 8

More Related Content

What's hot

Automatic Identification of Bug-Introducing Changes
Automatic Identification of Bug-Introducing ChangesAutomatic Identification of Bug-Introducing Changes
Automatic Identification of Bug-Introducing Changes
Thomas Zimmermann
 
Аварийный дамп – чёрный ящик упавшей JVM. Андрей Паньгин
Аварийный дамп – чёрный ящик упавшей JVM. Андрей ПаньгинАварийный дамп – чёрный ящик упавшей JVM. Андрей Паньгин
Аварийный дамп – чёрный ящик упавшей JVM. Андрей Паньгин
odnoklassniki.ru
 
Openframworks x Mobile
Openframworks x MobileOpenframworks x Mobile
Openframworks x Mobile
Janet Huang
 
Dat testing - An introduction to Java and Android Testing
Dat testing - An introduction to Java and Android TestingDat testing - An introduction to Java and Android Testing
Dat testing - An introduction to Java and Android Testing
Saúl Díaz González
 
Java awt
Java awtJava awt
Matching Game In Java
Matching Game In JavaMatching Game In Java
Matching Game In Java
cmkandemir
 

What's hot (6)

Automatic Identification of Bug-Introducing Changes
Automatic Identification of Bug-Introducing ChangesAutomatic Identification of Bug-Introducing Changes
Automatic Identification of Bug-Introducing Changes
 
Аварийный дамп – чёрный ящик упавшей JVM. Андрей Паньгин
Аварийный дамп – чёрный ящик упавшей JVM. Андрей ПаньгинАварийный дамп – чёрный ящик упавшей JVM. Андрей Паньгин
Аварийный дамп – чёрный ящик упавшей JVM. Андрей Паньгин
 
Openframworks x Mobile
Openframworks x MobileOpenframworks x Mobile
Openframworks x Mobile
 
Dat testing - An introduction to Java and Android Testing
Dat testing - An introduction to Java and Android TestingDat testing - An introduction to Java and Android Testing
Dat testing - An introduction to Java and Android Testing
 
Java awt
Java awtJava awt
Java awt
 
Matching Game In Java
Matching Game In JavaMatching Game In Java
Matching Game In Java
 

Similar to 5 Cool Things About PLSQL

Verilog Lecture3 hust 2014
Verilog Lecture3 hust 2014Verilog Lecture3 hust 2014
Verilog Lecture3 hust 2014
Béo Tú
 
How to tune a query - ODTUG 2012
How to tune a query - ODTUG 2012How to tune a query - ODTUG 2012
How to tune a query - ODTUG 2012
Connor McDonald
 
Verilog Lecture4 2014
Verilog Lecture4 2014Verilog Lecture4 2014
Verilog Lecture4 2014
Béo Tú
 
Exceptions Triggers function in SQL by Vasant Bhabad
Exceptions Triggers function in SQL by Vasant BhabadExceptions Triggers function in SQL by Vasant Bhabad
Exceptions Triggers function in SQL by Vasant Bhabad
vasant Bhabad
 
Triggers in plsql
Triggers in plsqlTriggers in plsql
Triggers in plsql
Arun Sial
 
The System of Automatic Searching for Vulnerabilities or how to use Taint Ana...
The System of Automatic Searching for Vulnerabilities or how to use Taint Ana...The System of Automatic Searching for Vulnerabilities or how to use Taint Ana...
The System of Automatic Searching for Vulnerabilities or how to use Taint Ana...Positive Hack Days
 
Integer security analysis using smt solver
Integer security analysis using smt solverInteger security analysis using smt solver
Integer security analysis using smt solver
Dharmalingam Ganesan
 
View triggers pg_east_20110325
View triggers pg_east_20110325View triggers pg_east_20110325
View triggers pg_east_20110325
David Fetter
 
JPC#8 Introduction to Java Programming
JPC#8 Introduction to Java ProgrammingJPC#8 Introduction to Java Programming
JPC#8 Introduction to Java ProgrammingPathomchon Sriwilairit
 
Triggers
TriggersTriggers
Lab07_Triggers.pptx
Lab07_Triggers.pptxLab07_Triggers.pptx
Lab07_Triggers.pptx
KhngNguyn81
 
The Inner Secrets of Compilers
The Inner Secrets of CompilersThe Inner Secrets of Compilers
The Inner Secrets of Compilers
IT MegaMeet
 
Cc code cards
Cc code cardsCc code cards
Cc code cards
ysolanki78
 
Delphi L08 Controls at Runtime P2
Delphi L08 Controls at Runtime P2Delphi L08 Controls at Runtime P2
Delphi L08 Controls at Runtime P2Mohammad Shaker
 
A New View of Database Views
A New View of Database ViewsA New View of Database Views
A New View of Database Views
Michael Rosenblum
 
Debugging TV Frame 0x09
Debugging TV Frame 0x09Debugging TV Frame 0x09
Debugging TV Frame 0x09
Dmitry Vostokov
 
Slides13.pdf
Slides13.pdfSlides13.pdf
Slides13.pdf
ssuser3b4934
 
Ch02 primitive-data-definite-loops
Ch02 primitive-data-definite-loopsCh02 primitive-data-definite-loops
Ch02 primitive-data-definite-loops
James Brotsos
 

Similar to 5 Cool Things About PLSQL (20)

Verilog Lecture3 hust 2014
Verilog Lecture3 hust 2014Verilog Lecture3 hust 2014
Verilog Lecture3 hust 2014
 
How to tune a query - ODTUG 2012
How to tune a query - ODTUG 2012How to tune a query - ODTUG 2012
How to tune a query - ODTUG 2012
 
Verilog Lecture4 2014
Verilog Lecture4 2014Verilog Lecture4 2014
Verilog Lecture4 2014
 
Exceptions Triggers function in SQL by Vasant Bhabad
Exceptions Triggers function in SQL by Vasant BhabadExceptions Triggers function in SQL by Vasant Bhabad
Exceptions Triggers function in SQL by Vasant Bhabad
 
Triggers in plsql
Triggers in plsqlTriggers in plsql
Triggers in plsql
 
The System of Automatic Searching for Vulnerabilities or how to use Taint Ana...
The System of Automatic Searching for Vulnerabilities or how to use Taint Ana...The System of Automatic Searching for Vulnerabilities or how to use Taint Ana...
The System of Automatic Searching for Vulnerabilities or how to use Taint Ana...
 
Module06
Module06Module06
Module06
 
Unit 4
Unit 4Unit 4
Unit 4
 
Integer security analysis using smt solver
Integer security analysis using smt solverInteger security analysis using smt solver
Integer security analysis using smt solver
 
View triggers pg_east_20110325
View triggers pg_east_20110325View triggers pg_east_20110325
View triggers pg_east_20110325
 
JPC#8 Introduction to Java Programming
JPC#8 Introduction to Java ProgrammingJPC#8 Introduction to Java Programming
JPC#8 Introduction to Java Programming
 
Triggers
TriggersTriggers
Triggers
 
Lab07_Triggers.pptx
Lab07_Triggers.pptxLab07_Triggers.pptx
Lab07_Triggers.pptx
 
The Inner Secrets of Compilers
The Inner Secrets of CompilersThe Inner Secrets of Compilers
The Inner Secrets of Compilers
 
Cc code cards
Cc code cardsCc code cards
Cc code cards
 
Delphi L08 Controls at Runtime P2
Delphi L08 Controls at Runtime P2Delphi L08 Controls at Runtime P2
Delphi L08 Controls at Runtime P2
 
A New View of Database Views
A New View of Database ViewsA New View of Database Views
A New View of Database Views
 
Debugging TV Frame 0x09
Debugging TV Frame 0x09Debugging TV Frame 0x09
Debugging TV Frame 0x09
 
Slides13.pdf
Slides13.pdfSlides13.pdf
Slides13.pdf
 
Ch02 primitive-data-definite-loops
Ch02 primitive-data-definite-loopsCh02 primitive-data-definite-loops
Ch02 primitive-data-definite-loops
 

More from Connor McDonald

Flashback ITOUG
Flashback ITOUGFlashback ITOUG
Flashback ITOUG
Connor McDonald
 
Sangam 19 - PLSQL still the coolest
Sangam 19 - PLSQL still the coolestSangam 19 - PLSQL still the coolest
Sangam 19 - PLSQL still the coolest
Connor McDonald
 
Sangam 19 - Analytic SQL
Sangam 19 - Analytic SQLSangam 19 - Analytic SQL
Sangam 19 - Analytic SQL
Connor McDonald
 
UKOUG - 25 years of hints and tips
UKOUG - 25 years of hints and tipsUKOUG - 25 years of hints and tips
UKOUG - 25 years of hints and tips
Connor McDonald
 
Sangam 19 - Successful Applications on Autonomous
Sangam 19 - Successful Applications on AutonomousSangam 19 - Successful Applications on Autonomous
Sangam 19 - Successful Applications on Autonomous
Connor McDonald
 
Sangam 2019 - The Latest Features
Sangam 2019 - The Latest FeaturesSangam 2019 - The Latest Features
Sangam 2019 - The Latest Features
Connor McDonald
 
UKOUG 2019 - SQL features
UKOUG 2019 - SQL featuresUKOUG 2019 - SQL features
UKOUG 2019 - SQL features
Connor McDonald
 
APEX tour 2019 - successful development with autonomous
APEX tour 2019 - successful development with autonomousAPEX tour 2019 - successful development with autonomous
APEX tour 2019 - successful development with autonomous
Connor McDonald
 
APAC Groundbreakers 2019 - Perth/Melbourne
APAC Groundbreakers 2019 - Perth/Melbourne APAC Groundbreakers 2019 - Perth/Melbourne
APAC Groundbreakers 2019 - Perth/Melbourne
Connor McDonald
 
OOW19 - Flashback, not just for DBAs
OOW19 - Flashback, not just for DBAsOOW19 - Flashback, not just for DBAs
OOW19 - Flashback, not just for DBAs
Connor McDonald
 
OOW19 - Read consistency
OOW19 - Read consistencyOOW19 - Read consistency
OOW19 - Read consistency
Connor McDonald
 
OOW19 - Slower and less secure applications
OOW19 - Slower and less secure applicationsOOW19 - Slower and less secure applications
OOW19 - Slower and less secure applications
Connor McDonald
 
OOW19 - Killing database sessions
OOW19 - Killing database sessionsOOW19 - Killing database sessions
OOW19 - Killing database sessions
Connor McDonald
 
OOW19 - Ten Amazing SQL features
OOW19 - Ten Amazing SQL featuresOOW19 - Ten Amazing SQL features
OOW19 - Ten Amazing SQL features
Connor McDonald
 
Latin America Tour 2019 - 18c and 19c featues
Latin America Tour 2019   - 18c and 19c featuesLatin America Tour 2019   - 18c and 19c featues
Latin America Tour 2019 - 18c and 19c featues
Connor McDonald
 
Latin America tour 2019 - Flashback
Latin America tour 2019 -  FlashbackLatin America tour 2019 -  Flashback
Latin America tour 2019 - Flashback
Connor McDonald
 
Latin America Tour 2019 - 10 great sql features
Latin America Tour 2019  - 10 great sql featuresLatin America Tour 2019  - 10 great sql features
Latin America Tour 2019 - 10 great sql features
Connor McDonald
 
Latin America Tour 2019 - pattern matching
Latin America Tour 2019 - pattern matchingLatin America Tour 2019 - pattern matching
Latin America Tour 2019 - pattern matching
Connor McDonald
 
Latin America Tour 2019 - slow data and sql processing
Latin America Tour 2019  - slow data and sql processingLatin America Tour 2019  - slow data and sql processing
Latin America Tour 2019 - slow data and sql processing
Connor McDonald
 
ANSI vs Oracle language
ANSI vs Oracle languageANSI vs Oracle language
ANSI vs Oracle language
Connor McDonald
 

More from Connor McDonald (20)

Flashback ITOUG
Flashback ITOUGFlashback ITOUG
Flashback ITOUG
 
Sangam 19 - PLSQL still the coolest
Sangam 19 - PLSQL still the coolestSangam 19 - PLSQL still the coolest
Sangam 19 - PLSQL still the coolest
 
Sangam 19 - Analytic SQL
Sangam 19 - Analytic SQLSangam 19 - Analytic SQL
Sangam 19 - Analytic SQL
 
UKOUG - 25 years of hints and tips
UKOUG - 25 years of hints and tipsUKOUG - 25 years of hints and tips
UKOUG - 25 years of hints and tips
 
Sangam 19 - Successful Applications on Autonomous
Sangam 19 - Successful Applications on AutonomousSangam 19 - Successful Applications on Autonomous
Sangam 19 - Successful Applications on Autonomous
 
Sangam 2019 - The Latest Features
Sangam 2019 - The Latest FeaturesSangam 2019 - The Latest Features
Sangam 2019 - The Latest Features
 
UKOUG 2019 - SQL features
UKOUG 2019 - SQL featuresUKOUG 2019 - SQL features
UKOUG 2019 - SQL features
 
APEX tour 2019 - successful development with autonomous
APEX tour 2019 - successful development with autonomousAPEX tour 2019 - successful development with autonomous
APEX tour 2019 - successful development with autonomous
 
APAC Groundbreakers 2019 - Perth/Melbourne
APAC Groundbreakers 2019 - Perth/Melbourne APAC Groundbreakers 2019 - Perth/Melbourne
APAC Groundbreakers 2019 - Perth/Melbourne
 
OOW19 - Flashback, not just for DBAs
OOW19 - Flashback, not just for DBAsOOW19 - Flashback, not just for DBAs
OOW19 - Flashback, not just for DBAs
 
OOW19 - Read consistency
OOW19 - Read consistencyOOW19 - Read consistency
OOW19 - Read consistency
 
OOW19 - Slower and less secure applications
OOW19 - Slower and less secure applicationsOOW19 - Slower and less secure applications
OOW19 - Slower and less secure applications
 
OOW19 - Killing database sessions
OOW19 - Killing database sessionsOOW19 - Killing database sessions
OOW19 - Killing database sessions
 
OOW19 - Ten Amazing SQL features
OOW19 - Ten Amazing SQL featuresOOW19 - Ten Amazing SQL features
OOW19 - Ten Amazing SQL features
 
Latin America Tour 2019 - 18c and 19c featues
Latin America Tour 2019   - 18c and 19c featuesLatin America Tour 2019   - 18c and 19c featues
Latin America Tour 2019 - 18c and 19c featues
 
Latin America tour 2019 - Flashback
Latin America tour 2019 -  FlashbackLatin America tour 2019 -  Flashback
Latin America tour 2019 - Flashback
 
Latin America Tour 2019 - 10 great sql features
Latin America Tour 2019  - 10 great sql featuresLatin America Tour 2019  - 10 great sql features
Latin America Tour 2019 - 10 great sql features
 
Latin America Tour 2019 - pattern matching
Latin America Tour 2019 - pattern matchingLatin America Tour 2019 - pattern matching
Latin America Tour 2019 - pattern matching
 
Latin America Tour 2019 - slow data and sql processing
Latin America Tour 2019  - slow data and sql processingLatin America Tour 2019  - slow data and sql processing
Latin America Tour 2019 - slow data and sql processing
 
ANSI vs Oracle language
ANSI vs Oracle languageANSI vs Oracle language
ANSI vs Oracle language
 

Recently uploaded

Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...
Product School
 
Knowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and backKnowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and back
Elena Simperl
 
Connector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonConnector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a button
DianaGray10
 
Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with Parameters
Safe Software
 
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMsTo Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
Paul Groth
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
Cheryl Hung
 
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
Product School
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
Product School
 
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
Product School
 
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Product School
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Inflectra
 
When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...
Elena Simperl
 
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
Product School
 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
DianaGray10
 
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
Sri Ambati
 
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdfFIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance
 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
Laura Byrne
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
James Anderson
 
Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
OnBoard
 

Recently uploaded (20)

Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...Designing Great Products: The Power of Design and Leadership by Chief Designe...
Designing Great Products: The Power of Design and Leadership by Chief Designe...
 
Knowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and backKnowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and back
 
Connector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonConnector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a button
 
Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with Parameters
 
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMsTo Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
 
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
 
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
 
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
 
When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...
 
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
 
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
 
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdfFIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
 
Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
 

5 Cool Things About PLSQL

  • 1. 1 Copyright © 2011, Oracle and/or its affiliates. All rights reserved. Insert Information Protection Policy Classification from Slide 8
  • 2. 2 Copyright © 2011, Oracle and/or its affiliates. All rights reserved. Insert Information Protection Policy Classification from Slide 8 Five things you probably didn’t know about PL/SQL Thomas Kyte http://asktom.oracle.com/
  • 3. 3 Who am I • Been with Oracle since 1993 • User of Oracle since 1987 • The “Tom” behind AskTom in Oracle Magazine www.oracle.com/oramag • Expert Oracle Database Architecture • Effective Oracle by Design • Expert One on One Oracle • Beginning Oracle
  • 4. 4 <Insert Picture Here> Five things you probably didn’t know about PL/SQL • Trigger Trickery • Why you need to ignore errors (really) • Elaboration Code • Implicit conversions are beyond evil • What About Roles…
  • 6. 6 <Insert Picture Here> Trigger Trickery • When do your triggers actually fire? • What do your triggers actually see? • How many times can a row level trigger fire? • Will your trigger actually fire? • Does your trigger prevent things from happening as you think they should?
  • 7. 7 <Insert Picture Here> Trigger Trickery • When do your triggers actually fire? • What do your triggers actually see? – Before trigger sees ‘nothing’ – Before for each row trigger sees what the row might look like (consistent read) and what that row might become (based on consistent read – After trigger sees the row as it was before and after the row update. This may or may not be what the row looks like after the modification is done! (because of what is coming) – After trigger sees ‘nothing’
  • 8. 8 <Insert Picture Here> Trigger Trickery • How many times can a trigger fire? – Before – twice – Before, for each row – twice per row – After, for each row – twice per row (except for the last row to be updated – it can only fire once ;) ) – After - once
  • 9. 9 Trigger Trickery ops$tkyte%ORA11GR2> create table t ( x int, y int ); Table created. ops$tkyte%ORA11GR2> insert into t values ( 1, 0 ); 1 row created. ops$tkyte%ORA11GR2> insert into t values ( 2, 0 ); 1 row created. ops$tkyte%ORA11GR2> insert into t values ( 3, 0 ); 1 row created.
  • 10. 10 Trigger Trickery ops$tkyte%ORA11GR2> create or replace trigger t_bu 2 before update on t 3 begin 4 dbms_output.put_line 5 ( 'I am the before trigger firing' ); 6 end; 7 / Trigger created.
  • 11. 11 Trigger Trickery ops$tkyte%ORA11GR2> create or replace trigger t_bufer 2 before update on t for each row 3 begin 4 dbms_output.put_line 5 ( 'BUFER: changing ' || 6 :old.x || ', ' || :old.y || 7 ' to ' || :new.x || ', ' || :new.y ); 8 end; 9 / Trigger created.
  • 12. 12 Trigger Trickery ops$tkyte%ORA11GR2> create or replace trigger t_aufer 2 after update on t for each row 3 begin 4 dbms_output.put_line 5 ( 'AUFER: changed ' || 6 :old.x || ', ' || :old.y || 7 ' to ' || :new.x || ', ' || :new.y ); 8 end; 9 / Trigger created.
  • 13. 13 Trigger Trickery ops$tkyte%ORA11GR2> create or replace trigger t_au 2 after update on t 3 begin 4 dbms_output.put_line 5 ( 'I am the after trigger firing' ); 6 end; 7 / Trigger created.
  • 14. 14 Trigger Trickery Session 1> update t set y = 100 where x = 3; I am the before trigger firing BUFER: changing 3, 0 to 3, 100 AUFER: changed 3, 0 to 3, 100 I am the after trigger firing 1 row updated. NOTE: no commit!
  • 15. 15 Trigger Trickery Session 2> update t set y = 42; NOTE: this is a second session, this blocks of course since the first session has row ‘3’ locked already.
  • 16. 16 Trigger Trickery Session 1> commit; Commit complete. NOTE: this is the first session, the one blocking the second session
  • 17. 17 Trigger Trickery Session 2> update t set y = 42; I am the before trigger firing BUFER: changing 1, 0 to 1, 42 AUFER: changed 1, 0 to 1, 42 BUFER: changing 2, 0 to 2, 42 AUFER: changed 2, 0 to 2, 42 BUFER: changing 3, 0 to 3, 42 <= <= how did that happen? I am the before trigger firing BUFER: changing 1, 0 to 1, 42 AUFER: changed 1, 0 to 1, 42 BUFER: changing 2, 0 to 2, 42 AUFER: changed 2, 0 to 2, 42 BUFER: changing 3, 100 to 3, 42 AUFER: changed 3, 100 to 3, 42 I am the after trigger firing 3 rows updated.
  • 18. 18 <Insert Picture Here> Trigger Trickery • So, what does that mean? – Never do anything non-transactional in a trigger – Pragma autonomous_transaction is a really bad idea in general – UTL_ packages – really bad idea. They do not roll back (utl_file, utl_http, utl_smtp, etc etc etc) – Even just setting global variables in a trigger can be tricky
  • 19. 19 <Insert Picture Here> Trigger Trickery • Will your trigger actually fire? – No, not always • Does your trigger prevent things from happening as you think they should? – Yes, sometimes
  • 20. 20 Trigger Trickery ops$tkyte%ORA11GR2> create table t ( x int, y int ); Table created. ops$tkyte%ORA11GR2> create or replace trigger t 2 before insert on t for each row 3 begin 4 :new.y := -:new.x; 5 end; 6 / Trigger created.
  • 21. 21 Trigger Trickery ops$tkyte%ORA11GR2> insert into t ( x, y ) values ( 100, 200 ); 1 row created. ops$tkyte%ORA11GR2> select * from t; X Y ---------- ---------- 100 -100 ops$tkyte%ORA11GR2> commit;
  • 22. 22 Trigger Trickery ops$tkyte%ORA11GR2> !cat t.ctl LOAD DATA INFILE * INTO TABLE t REPLACE FIELDS TERMINATED BY '|' ( x ,y ) BEGINDATA 100|42
  • 23. 23 Trigger Trickery ops$tkyte%ORA11GR2> !sqlldr / t direct=y SQL*Loader: Release 11.2.0.2.0 - Production on Tue Oct 4 13:13:49 2011 Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved. Load completed - logical record count 1.
  • 24. 24 Trigger Trickery ops$tkyte%ORA11GR2> select * from t; X Y ---------- ---------- 100 42 <<== that is wrong?
  • 25. 25 Trigger Trickery ops$tkyte%ORA11GR2> truncate table t; Table truncated. ops$tkyte%ORA11GR2> insert /*+ append */ into t select 100, 200 from dual; 1 row created. ops$tkyte%ORA11GR2> select * from t; X Y ---------- ---------- 100 -100 The fact we can select from that table tells us direct pathing did not happen
  • 26. 26 Trigger Trickery ops$tkyte%ORA11GR2> drop trigger t; Trigger dropped. ops$tkyte%ORA11GR2> truncate table t; Table truncated. ops$tkyte%ORA11GR2> insert /*+ append */ into t select 100, 200 from dual; 1 row created.
  • 27. 27 Trigger Trickery ops$tkyte%ORA11GR2> select * from t; select * from t * ERROR at line 1: ORA-12838: cannot read/modify an object after modifying it in parallel That is what you expect after a direct path insert! Triggers prevent it.
  • 28. 28 Why you want to ignore errors (really)
  • 29. 29 <Insert Picture Here> Please do ignore errors (really) • In my experience, error handling is done wrong more often than it is done right • You don’t want to catch all exceptions • You want to catch specific exceptions you are expecting (which means they aren’t exceptions) • You should ignore all others – or of you do catch them to clean up a resource, RE-RAISE them
  • 30. 30 Please do ignore errors (really) Begin p; end; Is really executed from a client as if it were: Begin savepoint X; p; Exception When others then rollback to X; RAISE; End;
  • 31. 31 Please do ignore errors (really) ops$tkyte%ORA11GR2> create table t ( x int check (x>0) ); Table created.
  • 32. 32 Please do ignore errors (really) ops$tkyte%ORA11GR2> create or replace procedure noexceptions 2 as 3 begin 4 insert into t values ( 1 ); 5 insert into t values ( 0 ); 6 end; 7 / Procedure created.
  • 33. 33 Please do ignore errors (really) ops$tkyte%ORA11GR2> create or replace procedure exceptions 2 as 3 begin 4 insert into t values ( 1 ); 5 insert into t values ( 0 ); 6 exception 7 when others 8 then 9 dbms_output.put_line( 'Error!!! ' || sqlerrm ); 10 end; 11 / Procedure created.
  • 34. 34 Please do ignore errors (really) ops$tkyte%ORA11GR2> exec noexceptions; BEGIN noexceptions; END; * ERROR at line 1: ORA-02290: check constraint (OPS$TKYTE.SYS_C0022770) violated ORA-06512: at "OPS$TKYTE.NOEXCEPTIONS", line 5 ORA-06512: at line 1 ops$tkyte%ORA11GR2> select * from t; no rows selected
  • 35. 35 Please do ignore errors (really) ops$tkyte%ORA11GR2> exec exceptions Error!!! ORA-02290: check constraint (OPS$TKYTE.SYS_C0022770) violated PL/SQL procedure successfully completed. ops$tkyte%ORA11GR2> select * from t; X ---------- 1
  • 36. 36 Please do ignore errors (really) It is ok to catch exceptions you are EXPECTING Begin … begin select x into y from t where …; exception when no_data_found then y := 42; end; …
  • 37. 37 Please do ignore errors (really) It is ok to catch exceptions at the TOP-LEVEL to log/change them. But re-raise them! Begin p; Exception When others then new_error_message := log_error_using_autonomous_transaction; raise_application_error( -20001, new_error_message ); End;
  • 38. 38 <Insert Picture Here> Please do ignore errors (really) • This is the #1 cause of bugs that I see time and time again • Do not catch exceptions at lower levels of code (most – 99.99999999% of code – should not have a when others) • Do catch it at the highest level to log it, or to make it “user friendly” • When others not followed by raise/raise_application_error should be a RED flag
  • 39. 39 Please do ignore errors (really) ops$tkyte%ORA11GR2> alter procedure bad_code compile 2 PLSQL_Warnings = 'enable:all' 3 reuse settings 4 / SP2-0805: Procedure altered with compilation warnings ops$tkyte%ORA11GR2> show errors procedure bad_code Errors for PROCEDURE BAD_CODE: LINE/COL ERROR -------- --------------------------------------------------------------- -- 1/1 PLW-05018: unit BAD_CODE omitted optional AUTHID clause; default value DEFINER used 9/8 PLW-06009: procedure "BAD_CODE" OTHERS handler does not end in RAISE or RAISE_APPLICATION_ERROR
  • 41. 41 <Insert Picture Here> Elaboration Code • Did you know that you can have some code run when a package is first ‘touched’ • Perform a one time setup operation • Without having to call an “init” routine, set a flag, etc
  • 42. 42 Elaboration Code ops$tkyte%ORA11GR2> create or replace package my_package 2 as 3 procedure p; 4 end; 5 / Package created.
  • 43. 43 Elaboration Code ops$tkyte%ORA11GR2> create or replace package body my_package 2 as 3 g_some_global varchar2(30); 4 5 procedure p 6 is 7 begin 8 dbms_output.put_line( g_some_global ); 9 end; 10 11 12 13 begin 14 g_some_global := 'result of some logic'; 15 end; 16 / Package body created.
  • 44. 44 Elaboration Code ops$tkyte%ORA11GR2> exec my_package.p result of some logic PL/SQL procedure successfully completed.
  • 45. 45 <Insert Picture Here> Elaboration Code • One time initialization – DBMS_LDAP callout for example 13 begin 14 g_some_global := dbms_ldap…; 15 end; 16 / – Load a lookup table – Any sort of complex initialization that cannot be done in a declare block
  • 47. 47 <Insert Picture Here> Implicit conversions are evil • SQL/PLSQL are too ‘user friendly’ – unlike C which complained about everything • Implicit conversions of strings to numbers, strings to dates, raw to string, etc are probably the #2 cause of bugs I see time and time again • Even worse are the implicit conversions that rely on default NLS settings!
  • 48. 48 Implicit conversions are evil ops$tkyte%ORA11GR2> create or replace procedure inj( p_date in date ) 2 as 3 l_rec all_users%rowtype; 4 c sys_refcursor; 5 l_query long; 6 begin 7 l_query := ' 8 select * 9 from all_users 10 where created = ''' ||p_date ||''''; -- DOUBLE implicit conversion! 11 12 dbms_output.put_line( l_query ); 13 open c for l_query; 14 15 for i in 1 .. 5 16 loop 17 fetch c into l_rec; 18 exit when c%notfound; 19 dbms_output.put_line( l_rec.username || '.....' ); 20 end loop; …
  • 49. 49 Implicit conversions are evil 7 l_query := ' 8 select * 9 from all_users 10 where created = ''' ||p_date ||''''; Creates a query that is semantically equivalent to: Where created = to_date( to_char( date-field ) ); Two implicit conversions – both of which rely on the NLS_DATE settings!
  • 50. 50 Implicit conversions are evil ops$tkyte%ORA11GR2> exec inj( sysdate ) select * from all_users where created = '04-OCT-11' PL/SQL procedure successfully completed.
  • 51. 51 Implicit conversions are evil ops$tkyte%ORA11GR2> alter session set 2 nls_date_format = 'dd-mon-yyyy"'' or ''a'' = ''a"'; Session altered.
  • 52. 52 Implicit conversions are evil ops$tkyte%ORA11GR2> exec inj( sysdate ) select * from all_users where created = '04-oct-2011' or 'a' = 'a' A..... EBRAPP..... EBRTBLS..... UTIL..... USER2..... PL/SQL procedure successfully completed.
  • 53. 53 Implicit conversions are evil ops$tkyte%ORA11GR2> alter session set 2 nls_date_format = '"''union select tname,0,null from tab--"'; Session altered. Select * from all_users where created = ''union select tname,0,null from tab--'
  • 54. 54 <Insert Picture Here> Implicit conversions are evil • What about performance? – Repeated conversions – Access path reductions – Partition elimination eliminated
  • 55. 55 Implicit conversions are evil ops$tkyte%ORA11GR2> declare 2 l_date varchar2(30) := '01-jan-2011'; 3 l_start number; 4 begin 5 l_start := dbms_utility.get_cpu_time; 6 7 for i in 1 .. 10 8 loop 9 for x in ( select * 10 from big_table.big_table 11 where created = l_date ) 12 loop 13 null; 14 end loop; 15 end loop; 16 17 dbms_output.put_line( 'CPU: ' || 18 to_char( dbms_utility.get_cpu_time-l_start ) ); 19 end; 20 / CPU: 132
  • 56. 56 Implicit conversions are evil ops$tkyte%ORA11GR2> declare 2 l_date date := to_date( '01-jan-2011', 'dd-mon-yyyy' ); 3 l_start number; 4 begin 5 l_start := dbms_utility.get_cpu_time; 6 7 for i in 1 .. 10 8 loop 9 for x in ( select * 10 from big_table.big_table 11 where created = l_date ) 12 loop 13 null; 14 end loop; 15 end loop; 16 17 dbms_output.put_line( 'CPU: ' || 18 to_char( dbms_utility.get_cpu_time-l_start ) ); 19 end; 20 / CPU: 94 30% less CPU in this case
  • 57. 57 Implicit conversions are evil ops$tkyte%ORA11GR2> create table t 2 ( x varchar2(20) constraint t_pk primary key, 3 y varchar2(30) 4 ); Table created. ops$tkyte%ORA11GR2> insert into t 2 select user_id, username 3 from all_users; 47 rows created. ops$tkyte%ORA11GR2> commit; Commit complete.
  • 58. 58 Implicit conversions are evil ops$tkyte%ORA11GR2> declare 2 l_rec t%rowtype; 3 l_key number := 5; 4 begin 5 select * into l_rec from t where x = l_key; 6 7 for x in (select plan_table_output 8 from TABLE( dbms_xplan.display_cursor() ) ) 9 loop 10 dbms_output.put_line( x.plan_table_output ); 11 end loop; 12 end; 13 /
  • 59. 59 Implicit conversions are evil SQL_ID 18796jgha0hwz, child number 0 ------------------------------------- SELECT * FROM T WHERE X = :B1 Plan hash value: 1601196873 -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | 3 (100)| | |* 1 | TABLE ACCESS FULL| T | 1 | 29 | 3 (0)| 00:00:01 | -------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter(TO_NUMBER("X")=:B1)
  • 60. 60 Implicit conversions are evil ops$tkyte%ORA11GR2> declare 2 l_rec t%rowtype; 3 l_key varchar2(20) := '5'; 4 begin 5 select * into l_rec from t where x = l_key; 6 7 for x in (select plan_table_output 8 from TABLE( dbms_xplan.display_cursor() ) ) 9 loop 10 dbms_output.put_line( '.'||x.plan_table_output ); 11 end loop; 12 end; 13 /
  • 61. 61 Implicit conversions are evil SQL_ID 18796jgha0hwz, child number 1 ------------------------------------- SELECT * FROM T WHERE X = :B1 Plan hash value: 1303508680 ------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | | | 1 (100)| | | 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 29 | 1 (0)| 00:00:01 | |* 2 | INDEX UNIQUE SCAN | T_PK | 1 | | 1 (0)| 00:00:01 | ------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("X"=:B1)
  • 62. 62 Implicit conversions are evil ops$tkyte%ORA11GR2> CREATE TABLE t 2 ( 3 dt date, 4 x int, 5 y varchar2(30) 6 ) 7 PARTITION BY RANGE (dt) 8 ( 9 PARTITION part1 VALUES LESS THAN(to_date('31-jan-2011', 'dd-mon-yyyy')), 10 PARTITION part2 VALUES LESS THAN(to_date('28-feb-2011', 'dd-mon-yyyy')) 11 ) 12 / Table created.
  • 63. 63 Implicit conversions are evil ops$tkyte%ORA11GR2> declare 2 l_date timestamp := timestamp'2011-01-15 00:00:00.000'; 3 l_count number; 4 begin 5 select count(*) into l_count from t where dt = l_date; 6 7 for x in (select plan_table_output 8 from TABLE( dbms_xplan.display_cursor() ) ) 9 loop 10 dbms_output.put_line( '.'||x.plan_table_output ); 11 end loop; 12 end; 13 /
  • 64. 64 Implicit conversions are evil SQL_ID 0t5m83d3m67q7, child number 0 ------------------------------------- SELECT COUNT(*) FROM T WHERE DT = :B1 Plan hash value: 3225603066 --------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop | --------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | 2 (100)| | | | | 1 | SORT AGGREGATE | | 1 | 9 | | | | | | 2 | PARTITION RANGE ALL| | 1 | 9 | 2 (0)| 00:00:01 | 1 | 2 | |* 3 | TABLE ACCESS FULL | T | 1 | 9 | 2 (0)| 00:00:01 | 1 | 2 | --------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - filter(INTERNAL_FUNCTION("DT")=:B1)
  • 65. 65 Implicit conversions are evil ops$tkyte%ORA11GR2> declare 2 l_date date := to_date( '15-jan-2011', 'dd-mon-yyyy' ); 3 l_count number; 4 begin 5 select count(*) into l_count from t where dt = l_date; 6 7 for x in (select plan_table_output 8 from TABLE( dbms_xplan.display_cursor() ) ) 9 loop 10 dbms_output.put_line( '.'||x.plan_table_output ); 11 end loop; 12 end; 13 /
  • 66. 66 Implicit conversions are evil .SQL_ID 0t5m83d3m67q7, child number 1 .------------------------------------- .SELECT COUNT(*) FROM T WHERE DT = :B1 . .Plan hash value: 3660200434 . .------------------------------------------------------------------------------------------------ .| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop | .------------------------------------------------------------------------------------------------ .| 0 | SELECT STATEMENT | | | | 2 (100)| | | | .| 1 | SORT AGGREGATE | | 1 | 9 | | | | | .| 2 | PARTITION RANGE SINGLE| | 1 | 9 | 2 (0)| 00:00:01 | KEY | KEY | .|* 3 | TABLE ACCESS FULL | T | 1 | 9 | 2 (0)| 00:00:01 | KEY | KEY | .------------------------------------------------------------------------------------------------ . .Predicate Information (identified by operation id): .--------------------------------------------------- . . 3 - filter("DT"=:B1)
  • 67. 67 <Insert Picture Here> Implicit conversions are evil • Lots and lots of bugs – What is ‘01/02/03’? – where column = to_char(sysdate) – what does that mean?
  • 69. 69 <Insert Picture Here> PL/SQL and roles • Quote: – To create without errors (to compile the subprogram or package successfully) requires these additional privileges: The owner of the subprogram or package must be explicitly granted the necessary object privileges for all objects referenced within the body of the code. – The owner cannot obtain required privileges through roles. Note by me: Not entirely true, but almost always true
  • 70. 70 <Insert Picture Here> PL/SQL and roles • Why is this the case? – Roles are for the hundreds/thousands of application users. You have very few application schemas that need to have compiled stored objects – Direct GRANTS make monitoring the set of privileges a schema needs infinitely easier than a massive hierarchy of roles (least privilege) – What should the effect of non-default, password protected, application enabled roles?
  • 71. 71 <Insert Picture Here> PL/SQL and roles – Two Modes • Definers Rights – Default method for stored compiled code – All code is compiled with base (no roles) privileges granted directly to the owner of the procedure.
  • 72. 72 <Insert Picture Here> PL/SQL and roles – Two Modes • Invokers Rights – Default method for anonymous blocks – Using authid current_user – All code is compiled with base privileges granted directly to the owner of the procedure. Nothing changes there – owner still needs direct access. – SQL rights are re-evaluated at runtime using the current set of privileges in place in the current session running the code. • Tables accessed at runtime might be different than tables checked against at compile time. – PL/SQL bindings are fixed at compile time.
  • 73. 73 Copyright © 2011, Oracle and/or its affiliates. All rights reserved. Insert Information Protection Policy Classification from Slide 8 ops$tkyte%ORA11GR2> create table t 2 as 3 select * 4 from all_users 5 where rownum <= 3; Table created. PL/SQL and roles – Two Modes
  • 74. 74 Copyright © 2011, Oracle and/or its affiliates. All rights reserved. Insert Information Protection Policy Classification from Slide 8 ops$tkyte%ORA11GR2> create or replace procedure show_user_info_ir 2 AUTHID CURRENT_USER 3 as 4 begin 5 dbms_output.put_line( '--------- IR Status ---------' ); 6 for x in (select sys_context('userenv', 'authenticated_identity' ) ai, 7 sys_context('userenv', 'current_schema') cs, 8 sys_context('userenv', 'current_schemaid') cs_id, 9 sys_context('userenv', 'current_user') cu 10 from dual ) 11 loop 12 dbms_output.put_line( 'authenticated identity: ' || x.ai ); 13 dbms_output.put_line( 'current schema : ' || x.cs ); 14 dbms_output.put_line( 'current schemaid : ' || x.cs_id ); 15 dbms_output.put_line( 'current user : ' || x.cu ); 16 end loop; 17 end; 18 / Procedure created. PL/SQL and roles – Two Modes
  • 75. 75 Copyright © 2011, Oracle and/or its affiliates. All rights reserved. Insert Information Protection Policy Classification from Slide 8 ops$tkyte%ORA11GR2> create or replace procedure show_user_info_dr 2 AUTHID DEFINER 3 as 4 begin 5 dbms_output.put_line( '--------- DR Status ---------' ); 6 for x in (select sys_context('userenv', 'authenticated_identity' ) ai, 7 sys_context('userenv', 'current_schema') cs, 8 sys_context('userenv', 'current_schemaid') cs_id, 9 sys_context('userenv', 'current_user') cu 10 from dual ) 11 loop 12 dbms_output.put_line( 'authenticated identity: ' || x.ai ); 13 dbms_output.put_line( 'current schema : ' || x.cs ); 14 dbms_output.put_line( 'current schemaid : ' || x.cs_id ); 15 dbms_output.put_line( 'current user : ' || x.cu ); 16 end loop; 17 end; 18 / Procedure created. PL/SQL and roles – Two Modes
  • 76. 76 Copyright © 2011, Oracle and/or its affiliates. All rights reserved. Insert Information Protection Policy Classification from Slide 8 ops$tkyte%ORA11GR2> create or replace procedure curr_user 2 AUTHID CURRENT_USER 3 as 4 begin 5 show_user_info_ir; 6 show_user_info_dr; 7 dbms_output.put_line( '--------- data ---------' ); 8 for x in (select * from t) 9 loop 10 dbms_output.put_line( x.username ); 11 end loop; 12 for x in (select * from ops$tkyte.t) 13 loop 14 dbms_output.put_line( x.username ); 15 end loop; 16 end; 17 / Procedure created. PL/SQL and roles – Two Modes Bound at compile time Checked with base privileges at compile time, re-bound at runtime
  • 77. 77 Copyright © 2011, Oracle and/or its affiliates. All rights reserved. Insert Information Protection Policy Classification from Slide 8 ops$tkyte%ORA11GR2> grant execute on curr_user to public; Grant succeeded. No other grants, not on OPS$TKYTE.T, not on show_user_info_* PL/SQL and roles – Two Modes
  • 78. 78 Copyright © 2011, Oracle and/or its affiliates. All rights reserved. Insert Information Protection Policy Classification from Slide 8 ops$tkyte%ORA11GR2> exec curr_user --------- IR Status --------- authenticated identity: tkyte current schema : OPS$TKYTE current schemaid : 274 current user : OPS$TKYTE --------- DR Status --------- authenticated identity: tkyte current schema : OPS$TKYTE current schemaid : 274 current user : OPS$TKYTE --------- data --------- SYS SYSTEM OUTLN SYS SYSTEM OUTLN PL/SQL and roles – Two Modes
  • 79. 79 Copyright © 2011, Oracle and/or its affiliates. All rights reserved. Insert Information Protection Policy Classification from Slide 8 ops$tkyte%ORA11GR2> connect scott/tiger Connected. PL/SQL and roles – Two Modes
  • 80. 80 Copyright © 2011, Oracle and/or its affiliates. All rights reserved. Insert Information Protection Policy Classification from Slide 8 scott%ORA11GR2> exec ops$tkyte.curr_user --------- IR Status --------- authenticated identity: scott current schema : SCOTT current schemaid : 83 current user : SCOTT --------- DR Status --------- authenticated identity: scott current schema : OPS$TKYTE current schemaid : 274 current user : OPS$TKYTE --------- data --------- BEGIN ops$tkyte.curr_user; END; * ERROR at line 1: ORA-00942: table or view does not exist ORA-06512: at "OPS$TKYTE.CURR_USER", line 8 ORA-06512: at line 1 PL/SQL and roles – Two Modes
  • 81. 81 Copyright © 2011, Oracle and/or its affiliates. All rights reserved. Insert Information Protection Policy Classification from Slide 8 scott%ORA11GR2> create table t ( x int ); Table created. PL/SQL and roles – Two Modes
  • 82. 82 Copyright © 2011, Oracle and/or its affiliates. All rights reserved. Insert Information Protection Policy Classification from Slide 8 scott%ORA11GR2> exec ops$tkyte.curr_user --------- IR Status --------- authenticated identity: scott current schema : SCOTT current schemaid : 83 current user : SCOTT --------- DR Status --------- authenticated identity: scott current schema : OPS$TKYTE current schemaid : 274 current user : OPS$TKYTE --------- data --------- BEGIN ops$tkyte.curr_user; END; * ERROR at line 1: ORA-01007: variable not in select list ORA-06512: at "OPS$TKYTE.CURR_USER", line 8 ORA-06512: at line 1 PL/SQL and roles – Two Modes
  • 83. 83 Copyright © 2011, Oracle and/or its affiliates. All rights reserved. Insert Information Protection Policy Classification from Slide 8 scott%ORA11GR2> create table t ( x int, y int, z int ); Table created. PL/SQL and roles – Two Modes
  • 84. 84 Copyright © 2011, Oracle and/or its affiliates. All rights reserved. Insert Information Protection Policy Classification from Slide 8 scott%ORA11GR2> exec ops$tkyte.curr_user --------- IR Status --------- authenticated identity: scott current schema : SCOTT current schemaid : 83 current user : SCOTT --------- DR Status --------- authenticated identity: scott current schema : OPS$TKYTE current schemaid : 274 current user : OPS$TKYTE --------- data --------- BEGIN ops$tkyte.curr_user; END; * ERROR at line 1: ORA-00932: inconsistent datatypes: expected DATE got NUMBER ORA-06512: at "OPS$TKYTE.CURR_USER", line 8 ORA-06512: at line 1 PL/SQL and roles – Two Modes
  • 85. 85 Copyright © 2011, Oracle and/or its affiliates. All rights reserved. Insert Information Protection Policy Classification from Slide 8 scott%ORA11GR2> create table t ( x varchar2(30), y number, z date ); Table created. scott%ORA11GR2> insert into t values ( 'hello', 0, sysdate ); 1 row created. PL/SQL and roles – Two Modes
  • 86. 86 Copyright © 2011, Oracle and/or its affiliates. All rights reserved. Insert Information Protection Policy Classification from Slide 8 scott%ORA11GR2> exec ops$tkyte.curr_user --------- IR Status --------- authenticated identity: scott current schema : SCOTT current schemaid : 83 current user : SCOTT --------- DR Status --------- authenticated identity: scott current schema : OPS$TKYTE current schemaid : 274 current user : OPS$TKYTE --------- data --------- hello BEGIN ops$tkyte.curr_user; END; * ERROR at line 1: ORA-00942: table or view does not exist ORA-06512: at "OPS$TKYTE.CURR_USER", line 12 ORA-06512: at line 1 PL/SQL and roles – Two Modes
  • 87. 87 Copyright © 2011, Oracle and/or its affiliates. All rights reserved. Insert Information Protection Policy Classification from Slide 8 scott%ORA11GR2> connect / Connected. ops$tkyte%ORA11GR2> create or replace procedure curr_user 2 AUTHID CURRENT_USER 3 as 4 begin 5 show_user_info_ir; 6 show_user_info_dr; 7 dbms_output.put_line( '--------- data ---------' ); 8 for x in (select username, user_id, created from t) 9 loop 10 dbms_output.put_line( x.username ); 11 end loop; 12 end; 13 / Procedure created. PL/SQL and roles – Two Modes
  • 88. 88 Copyright © 2011, Oracle and/or its affiliates. All rights reserved. Insert Information Protection Policy Classification from Slide 8 ops$tkyte%ORA11GR2> connect scott/tiger Connected. PL/SQL and roles – Two Modes
  • 89. 89 Copyright © 2011, Oracle and/or its affiliates. All rights reserved. Insert Information Protection Policy Classification from Slide 8 scott%ORA11GR2> exec ops$tkyte.curr_user --------- IR Status --------- authenticated identity: scott current schema : SCOTT current schemaid : 83 current user : SCOTT --------- DR Status --------- authenticated identity: scott current schema : OPS$TKYTE current schemaid : 274 current user : OPS$TKYTE --------- data --------- BEGIN ops$tkyte.curr_user; END; * ERROR at line 1: ORA-00904: "CREATED": invalid identifier ORA-06512: at "OPS$TKYTE.CURR_USER", line 8 ORA-06512: at line 1 PL/SQL and roles – Two Modes
  • 90. 90 <Insert Picture Here> PL/SQL and roles – Two Modes • Definers Rights comes first, it is the default, it should be the default. It is correct 99.99999999% of the time • Invokers Rights are good for – Routines that need to run “as caller”. Running as the owner would/could cause security issues (think SYS owned code) – It is infrequently executed or doesn’t use SQL – It uses dynamic SQL (typically). It is not bound to a fixed set of tables. It is a utility • DUMP_CSV() • PRINT_TABLE()
  • 91. 91 <Insert Picture Here> PL/SQL and roles – Two Modes • Invokers Rights will – Lose the dependency mechanism • They typically use dynamic SQL and even static is dynamic! – Reduce the reliability of the stored code • No compile time security checks for SQL really, short of the owner! • Everything good about static SQL is lost typically – Since SQL object references are not known until runtime and could be different for everyone, you could flood the shared pool – It is harder to develop and debug
  • 92. 92 <Insert Picture Here> PL/SQL and roles – Two Modes • In my opinion – The loss of roles is not an issue for stored procedures – You want the concept of LEAST PRIVILEGE – You want the ability to see exactly what an application schema can and cannot do – The ambiguity presented by non-default roles, etc is gone – The performance hit we would necessarily take is removed – Invokers rights should be used very sparingly
  • 93. 93 Copyright © 2011, Oracle and/or its affiliates. All rights reserved. Insert Information Protection Policy Classification from Slide 8 Q&A
  • 94. 94 Copyright © 2011, Oracle and/or its affiliates. All rights reserved. Insert Information Protection Policy Classification from Slide 8
  • 95. 95 Copyright © 2011, Oracle and/or its affiliates. All rights reserved. Insert Information Protection Policy Classification from Slide 8