Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
NOTE 
itty bitty fonts in this 
presentation 
SQL> exec sample_font 
Can you read this ? 
1
Connor McDonald 
OracleDBA 
co.uk 
2
3
bio slide 
5
gratuitous book plug 
6
7
gratuitous swim plug 
8
9
"why bother?" 
10
2013 2014 2015 2016 2017 2018 2019 2020 2021 
12c 12.1.0.2 12.2 
management 
visibility 
12c 
desupported 
"pilot"
1) know what’s coming 
12
don’t reinvent
15 
2) there's a lot in 12c !
16 
but not widely advertised
17 
because ...
18 
blah 
blah 
multi tenant 
blah
19 
blah 
blah 
blah
3) our use of the db is simpler 
20
21 
Value 
DB 
mainframe client 
server 
web soa 
Code 
1209018910123456789
<warning> 
</warning>
25 
@connor_mc_d 
connormcdonald.wordpress.com
26 
first impressions
27
28 
SQL> create user DEV_TESTING 
2 identified by MYPASS; 
create user DEV_TESTING identified by MYPASS 
* 
ERROR at line ...
29 
be patient
30
31 
or let someone else do it
32 
http://www.oracle.com/technetwork/community/developer-vm/index.html
33
34 
"Feature:" 
total recall
35
36 
11g feature !
37 
why ?
38 
we've all done it...
39 
job to job to job...
40 
auditing row changes
41 
SQL> desc T 
Name Null? Type 
----------------------------- -------- ------------- 
OWNER NOT NULL VARCHAR2(30) 
OBJEC...
42 
SQL> create or replace 
2 trigger AUDIT_TRG 
3 after insert or update or delete on T 
4 for each row 
5 declare 
6 v_a...
43 
works but slow...
44 
SQL> insert into T 
2 select owner, object_name 
3 from all_objects 
4 where rownum <= 10000; 
INSERT INTO T_AUDIT 
VA...
45 
if you were diligent
46 
bulk binding
47 
create or replace 
package T_PKG is 
type each_row is record ( action varchar2(1), 
owner varchar2(30), 
object_name v...
48 
create or replace 
trigger AUDIT_TRG1 
before insert or update or delete on T 
begin 
t_pkg.g.delete; 
end; 
/
49 
create or replace 
trigger AUDIT_TRG2 
after insert or update or delete on T 
for each row 
begin 
if updating or inse...
50 
create or replace 
trigger AUDIT_TRG3 
after insert or update or delete on T 
declare 
v_action varchar2(1) := 
case w...
51 
SQL> insert into T 
2 select owner, object_name 
3 from all_objects 
4 where rownum <= 10000; 
INSERT INTO T_AUDIT 
VA...
52 
compound trigger 
11g
but ... 
53
a better, faster, robust version ... 
54
... total recall 
11g 
55
SQL> create tablespace SPACE_FOR_ARCHIVE 
2 datafile 'C:ORACLEDB11ARCH_SPACE.DBF' 
3 size 100M; 
Tablespace created. 
56
SQL> CREATE FLASHBACK ARCHIVE longterm 
2 TABLESPACE space_for_archive 
3 RETENTION 1 YEAR; 
Flashback archive created. 
5...
SQL> ALTER TABLE EMP FLASHBACK ARCHIVE LONGTERM; 
Table altered. 
58
SQL> select * from EMP; 
-------------------------------------------------- 
| Id | Operation | Name | Rows | Bytes | 
---...
[after DML and time passing] 
SQL> select * from EMP 
2 AS OF TIMESTAMP SYSDATE-365; 
------------------------------------...
SQL> select table_name 
2 from user_tables 
3 / 
TABLE_NAME 
--------------------------- 
SYS_FBA_HIST_71036 
SYS_FBA_TCRV...
"I don't need to look back in time..." 
62
but can also be your audit ! 
63
SQL> alter table EMP add 
2 CREATE_TS timestamp default systimestamp; 
SQL> update EMP 
2 set sal = sal*10 
3 where empno ...
SQL> select empno, ename, job, sal, comm, 
2 nvl(VERSIONS_STARTTIME,CREATE_TS) TS 
3 ,nvl(VERSIONS_OPERATION,'I') OP 
4 fr...
so why didn't we ? 
66
reason 1 
67
separately licensed :-( 
69
can 12c help ? 
70
rebadged 
71
flashback data archive 
72
free ! 
73
let 
74 
me 
repeat
oracle feature that is free ! 
75
basis versus advanced 
76
compression 
choose your cost 
77 
partitioning
reason 2 
78
"yeah...but who ? where ? how ?" 
79
SQL> alter table EMP add UPDATED_BY varchar2(10); 
Table altered. 
SQL> alter table EMP add UPDATED_PGM varchar2(10); 
Tab...
can 12c help ? 
81
context extension 
82
SQL> begin 
2 dbms_flashback_archive.set_context_level( 
3 level=> 'ALL'); 
4 end; 
PL/SQL procedure successfully complete...
SQL> update EMP 
2 set sal = sal*10 
3 where empno = 7499; 
1 row updated. 
SQL> commit; 
84
SQL> select XID from SYS_FBA_HIST_510592; 
XID 
---------------- 
09000B00C7080000 
85
SQL> set serverout on 
SQL> begin 
2 dbms_output.put_line( 
3 dbms_flashback_archive.get_sys_context ( 
4 '09000B00C708000...
87
SQL> desc SYS.SYS_FBA_CONTEXT_AUD 
Name Null? Type 
------------------------- -------- ------------------ 
XID RAW(8) 
ACT...
SQL> @pt "select * from SYS.SYS_FBA_CONTEXT_AUD 
where xid = '09000B00C7080000'" 
XID : 09000B00C7080000 
AUTHENTICATED_ID...
SQL> select empno, ename, job, sal, comm, 
2 VERSIONS_XID 
3 from EMP 
4 versions between timestamp 
5 timestamp '2014-02-...
SQL> select ... 
2 from 
3 ( select 
4 empno, ename, job, 
5 sal, comm, VERSIONS_XID 
6 from EMP 
7 versions between times...
so think about “total recall” 
92 
free in 11.2.0.4 as well
secure 
read only 
93
efficient 
fdba 
94
all your history... 
95
all your audit... 
96
be careful... 
silent errors 
97
SQL> ALTER TABLE EMP FLASHBACK ARCHIVE LONGTERM; 
Table altered. 
Flashback Archive: 
Error ORA-1950 in SQL 
create table ...
data in the past ...
... to data at "any" time
Feature 
temporal validity
wtf
very common
"when" is a row valid
SQL> CREATE TABLE emp_temporal ( 
2 empno NUMBER, 
3 name VARCHAR2(30), 
4 sal NUMBER, 
5 deptno NUMBER, 
6 start_dt DATE,...
12c part of the definition
SQL> CREATE TABLE emp_temporal ( 
2 empno NUMBER, 
3 name VARCHAR2(30), 
4 sal NUMBER, 
5 deptno NUMBER, 
6 start_dt DATE,...
examples
SQL> select * from emp_temporal 
2 order by empno, start_dt; 
EMPNO NAME SAL DEPTNO START_DT END_DT 
---------- --------- ...
SQL> select * from emp_temporal 
2 as of period for valid_range '01-FEB-14'; 
EMPNO NAME SAL DEPTNO START_DT END_DT 
-----...
so what's happening ?
another new feature
what is the real query 
113
114 
SQL> set autotrace traceonly stat 
SQL> select * from MY_VIEW 
2 where CREATED > sysdate 
Statistics 
---------------...
115 
SQL> variable c clob 
SQL> begin 
2 dbms_utility.expand_sql_text 
3 ( 'select * from MY_VIEW'|| 
4 'where created > s...
116 
SQL> create or replace 
2 view MY_VIEW as 
3 select 
4 o.owner, 
5 o.created, 
6 s.bytes, 
7 s.tablespace_name 
8 fro...
117 
SELECT "A1"."OWNER" "OWNER", 
"A1"."NAME" "NAME", 
"A1"."CREATED" "CREATED", 
"A1"."BYTES" "BYTES", 
"A1"."TABLESPACE...
118 
"A4"."HEADER_BLOCK", 
"A4"."SEGMENT_TYPE_ID", 
"A4"."BUFFER_POOL_ID", 
"A4"."SEGMENT_FLAGS", 
"A4"."SEGMENT_OBJD", 
"...
119 
"A198"."SUBNAME" "PARTITION_NAME", 
"A196"."OBJECT_TYPE" "SEGMENT_TYPE", 
"A195"."TYPE#" "SEGMENT_TYPE_ID",DECODE(BIT...
120 
DECODE(BITAND("A209"."PROPERTY",8192),8192,'NESTED TABLE','TABLE') 
"OBJECT_TYPE", 
2 "OBJECT_TYPE_ID",5 "SEGMENT_TYP...
121 
"A205"."TS#" "TS_NUMBER" FROM "SYS"."INDPART$" "A205") UNION ALL 
(SELECT 'LOBSEGMENT' "OBJECT_TYPE",21 "OBJECT_TYPE_...
122 
"A195"."FILE#"="A194"."RELFILE#") UNION ALL 
(SELECT NVL("A193"."NAME",'SYS') "OWNER", 
"A191"."NAME" "SEGMENT_NAME",...
123 
"A191"."TS#"="A189"."TS#" AND 
"A191"."FILE#"="A189"."RELFILE#") UNION ALL 
(SELECT NVL("A188"."NAME",'SYS') "OWNER",...
124 
"A186"."TYPE#"<>6 AND 
"A186"."TYPE#"<>8 AND 
"A186"."TYPE#"<>10 AND 
"A186"."TYPE#"<>11 AND 
"A186"."TS#"="A185"."TS...
125 
"SYS"."TS$" "A183", 
"SYS"."SEG$" "A182", 
"SYS"."FILE$" "A181" WHERE "A182"."TS#"="A183"."TS#" AND 
"A182"."USER#"="...
16 ... 
126 
more 
pages
back to temporal validity 
127
SQL> variable c clob 
SQL> begin 
2 dbms_utility.expand_sql_text( 
3 q'{select * from emp_temporal 
4 as of period for val...
SQL> print c 
C 
------------------------------------------------ 
SELECT 
"A1"."EMPNO" 
... 
FROM ( 
SELECT "A2"."EMPNO" ...
existing tables
SQL> desc EMPLOYEE 
Name Null? Type 
------------------------- -------- --------------- 
EMPNO NUMBER(4) 
ENAME VARCHAR2(1...
SQL> desc EMPLOYEE 
Name Null? Type 
------------------------- -------- --------------- 
EMPNO NUMBER(4) 
ENAME VARCHAR2(1...
SQL> select column_name , hidden_column 
2 from user_tab_cols 
3 where table_name = 'EMPLOYEE' 
4 order by column_id; 
COL...
multi temporal validity
SQL> alter table EMP_TEMPORAL add period for CAL_RANGE; 
Table altered. 
SQL> alter table EMP_TEMPORAL add period for FINY...
maybe a 12.x feature ?
no temporal constraints
SQL> alter table EMP_TEMPORAL add primary key (empno); 
Table altered. 
SQL> insert into EMP_TEMPORAL 
2 (empno, name, sta...
add START_DT to primary key ?
no temporal validation
SQL> insert into EMP_TEMPORAL 
2 (empno, name, start_dt, end_dt ) 
3 values (10,'JONES', '01-JAN-14','01-MAY-14'); 
1 row ...
no temporal DML
SQL> update EMP_TEMPORAL 
2 as of period for valid_range '01-FEB-14' 
3 set sal = 10 
4 where empno = 20; 
as of period fo...
SQL> update ( 
2 select * from EMP_TEMPORAL 
3 as of period for valid_range '01-FEB-14' 
4 where empno = 7369 
5 ) 
6 set ...
"Temporal validity is not supported 
with a multitenant container 
database" 
(12.1.0.1)
Feature 
invisible columns
have been there "forever"
function based indexes
set column unused
SQL> create table T 
2 ( x int, 
3 y int); 
Table created. 
SQL> create index IX on T (x+0); 
Index created. 
SQL> alter t...
SQL> select column_name, data_default 
2 from USER_TAB_COLS 
3 where table_name = 'T' 
4 order by column_id; 
COLUMN_NAME ...
now exposed to us
SQL> create table T ( c1 int, c2 int, c3 int ); 
SQL> desc T 
Name Null? Type 
---------------------------- -------- -----...
and an idiosyncracy...
SQL> alter table T modify c1 visible; 
SQL> desc T 
Name Null? Type 
---------------------------- -------- ------- 
C2 NUM...
requires code discipline
SQL> desc T 
Name Null? Type 
---------------------- -------- -------------------- 
C1 NUMBER(38) 
C2 NUMBER(38) 
C3 NUMBE...
SQL> alter table T modify c1 invisible; 
Table altered. 
SQL> alter table T modify c1 visible; 
Table altered. 
SQL> desc ...
SQL> exec P 
PL/SQL procedure successfully completed. 
SQL> select c1,c2,c3 from t; 
C1 C2 C3 
---------- ---------- -----...
SQL> create or replace 
2 procedure FIX_COLS(p_tab varchar2, p_col_list varchar2) is 
3 l_col_list varchar2(1000) := p_col...
SQL> exec FIX_COLS('T','C1,C2,C3'); 
PL/SQL procedure successfully completed. 
SQL> desc T 
Name Null? Type 
-------------...
so what's the appeal ?
rollout new code online
SQL> create table T ( c1 int, c2 int ) ; 
Table created. 
SQL> create or replace 
2 procedure BAD_APP is 
3 begin 
4 inser...
new application
SQL> alter table T add c3 int; 
Table altered. 
SQL> create or replace 
2 procedure NEW_APP is 
3 begin 
4 for i in ( sele...
SQL> exec NEW_APP; 
28 
28 
15 
15 
29 
29 
25 
25 
54 
PL/SQL procedure successfully completed.
SQL> exec BAD_APP 
BEGIN BAD_APP; END; 
* 
ERROR at line 1: 
ORA-06550: line 1, column 7: 
PLS-00905: object SCOTT.BAD_APP...
SQL> alter table T modify c3 invisible; 
Table altered. 
SQL> exec NEW_APP; 
28 
28 
15 
15 
29 
29 
25 
25 
54 
PL/SQL pr...
tools
SQL> create table T ( c1 int, c2 int invisible); 
Table created. 
SQL> desc T 
Name Null? Type 
------------------------- ...
SQL> alter table T add "C3 (INVISIBLE)" int; 
Table altered. 
SQL> desc T 
Name Null? Type 
------------------------- ----...
176 
Feature: 
better truncate
177 
SQL> create table PARENT ( p int primary key ); 
Table created. 
SQL> create table CHILD 
2 ( c int primary key, 
3 p...
178 
SQL> truncate table PARENT; 
truncate table PARENT 
* 
ERROR at line 1: 
ORA-02266: unique/primary keys in table 
ref...
179 
12c
180 
SQL> truncate table PARENT cascade; 
Table truncated.
181 
SQL> alter table child modify 
2 constraint CHILD_FK on delete cascade; 
ERROR at line 1: 
ORA-00933: SQL command not...
182 
full cascade
183 
referential partitions
184 
Feature 
session level sequence
185 
SQL> create sequence SESS_SEQ session; 
Sequence created.
186 
SQL> select sess_seq.nextval from dual; 
NEXTVAL 
---------- 
1 
SQL> conn scott/tiger 
Connected. 
SQL> select sess_...
187 
contention
188 
SQL> create sequence NORMAL cache 1000; 
Sequence created. 
SQL> alter session set sql_trace = true; 
Session altered...
189 
SQL> insert into GTT 
2 select SESS_SEQ.NEXTVAL 
3 from dual 
4 connect by level < 50000; 
49999 rows created. 
SQL> ...
190 
insert into GTT 
select SESS_SEQ.NEXTVAL 
from dual 
connect by level < 50000 
call count cpu elapsed disk query 
---...
191 
insert into GTT 
select NORMAL.NEXTVAL 
from dual 
connect by level < 50000 
call count cpu elapsed disk query 
-----...
192 
update SEQ$ 
set increment$=:2,minvalue=:3,maxvalue=:4, 
cycle#=:5,order$=:6, 
cache=:7,highwater=:8,audit$=:9, 
flag...
193 
but ...
Lyrics 
"Players gonna play, play, play, play, play 
Haters gonna hate, hate, hate, hate, hate 
Gonna shake, shake, shake,...
196 
substance
197 
why ?
198 
SQL> select X 
2 from GTT; 
X 
---------- 
1 
2 
3 
4 
5 
6 
7 
8 
9 
... 
SQL> select X 
2 from GTT; 
X 
---------- ...
199
200 
please let me know ....
201 
perhaps more potential ...
202 
SQL> alter sequence SEQ 
2 maxvalue 1000000 partition 8; 
Sequence altered. 
SQL> select seq.nextval x from dual; 
X ...
203 
Feature 
defaults
204 
the most common ...
205 
and the absolute worst ...
206 
usage of triggers
207 
SQL> create sequence seq; 
Sequence created. 
SQL> create table T ( pk number , c1 int); 
Table created. 
SQL> create...
208 
SQL> insert into T values (10,20); 
1 row created. 
SQL> select * from T; 
PK C1 
---------- ---------- 
1 20
209 
we got smarter
210 
SQL> create or replace 
2 trigger FILL_IN_PK 
3 before insert on T 
4 for each row 
5 when ( new.pk is null ) 
6 begi...
triggers
over rated ... 
for that stuff
insert /* with trigger */ into T 
select rownum, rownum 
from dual connect by level <= 50000 
call count cpu elapsed disk ...
insert /* without trigger */ into T 
select rownum, rownum 
from dual connect by level <= 50000 
call count cpu elapsed di...
12c ... finally !
216 
SQL> create table T ( 
2 pk number default seq.nextval, 
3 c1 int); 
Table created. 
Oracle 7, June 1992
217 
SQL> insert into T ( c1 ) values ( 0); 
SQL> select * from T; 
PK C1 
---------- ---------- 
2 0 
SQL> insert into T ...
insert /* with default */ into T 
select rownum, rownum 
from dual connect by level <= 50000 
call count cpu elapsed disk ...
other default improvements
"identity"
221 
SQL> drop table t purge; 
Table dropped. 
SQL> create table T 
2 ( pk number generated as identity , 
3 c1 int); 
Tab...
222 
SQL> @pr "select * from user_sequences" 
SEQUENCE_NAME : ISEQ$$_414914 
MIN_VALUE : 1 
MAX_VALUE : 999999999999999999...
223 
SQL> create table T 
2 ( pk number 
3 generated as identity (cache 1000) 
4 , c1 int); 
Table created. 
SQL> insert i...
more null control
before 12c
226 
SQL> create table T ( 
2 pk int, 
3 status varchar2(1) default 'N' ); 
Table created. 
SQL> insert into T (pk) values...
227 
SQL> select * from T; 
PK STATUS 
---------- ------ 
1 N 
2 N 
3
workarounds ugly
229 
SQL> create or replace 
2 procedure ins(p_pk int, p_status varchar2) is 
3 begin 
4 if p_status is null then 
5 inser...
12c "on null"
231 
SQL> create table T ( 
2 pk int, 
3 status varchar2(1) default on null 'N' , 
4 start_date date default on null 
5 tr...
Feature 
PL/SQL debugging
it all starts off easy
SQL> create or replace procedure P is 
2 x int; 
3 y int; 
4 begin 
5 
6 x := 10; 
7 
8 select count(*) 
9 into y 
10 from...
SQL> exec P; 
BEGIN P; END; 
* 
ERROR at line 1: 
ORA-01476: divisor is equal to zero 
ORA-06512: at "SCOTT.P", line 13 
O...
SQL> create or replace procedure P is 
2 x int; 
3 y int; 
4 begin 
5 
6 x := 10; 
7 
8 select count(*) 
9 into y 
10 from...
... and downhill from there
SQL> create or replace procedure P is 
2 x int; 
3 y int; 
4 begin 
5 
6 x := 10; 
7 
8 select count(*) 
9 into y 
10 from...
SQL> exec P; 
BEGIN P; END; 
* 
ERROR at line 1: 
ORA-01476: divisor is equal to 
zero 
ORA-06512: at "SCOTT.P", line 22
SQL> create or replace procedure P is 
2 x int; 
3 y int; 
4 begin 
5 
6 x := 10; 
7 
8 select count(*) 
9 into y 
10 from...
SQL> create or replace procedure P is 
2 x int; 
3 y int; 
4 begin 
5 
6 x := 10; 
7 
8 select count(*) 
9 into y 
10 from...
SQL> exec P; 
----- PL/SQL Call Stack ----- 
object line object 
handle number name 
0x14b1e3900 21 procedure SCOTT.P 
0x1...
SQL> create or replace procedure P is 
2 x int; 
3 y int; 
4 l_debug varchar2(4000); 
5 begin 
6 l_debug := dbms_utility.f...
SQL> exec P; 
----- PL/SQL Call Stack ----- 
object line object 
handle number name 
0x14b1e3900 16 procedure SCOTT.P 
0x1...
SQL> create or replace procedure P is 
2 x int; 
3 y int; 
4 l_debug varchar2(4000); 
5 begin 
6 l_debug := dbms_utility.f...
SQL> exec P; 
0x14b1e3900 16 procedure SCOTT.P 
BEGIN P; END; 
* 
ERROR at line 1: 
ORA-01476: divisor is equal to zero 
O...
10g got better
DBMS_UTILITY.FORMAT_ERROR_BACKTRACE
SQL> create or replace procedure P is 
2 x int; 
3 y int; 
4 l_debug varchar2(4000); 
5 begin 
6 l_debug := dbms_utility.f...
SQL> exec P; 
ORA-06512: at "SCOTT.P", line 17 
BEGIN P; END; 
* 
ERROR at line 1: 
ORA-01476: divisor is equal to zero 
O...
12c .... finally
UTL_CALL_STACK
SQL> create or replace procedure P is 
2 x int; 
3 y int; 
4 begin 
5 x := 10; 
6 
... 
17 
18 exception 
19 when others t...
SQL> exec P; 
21-P 
1-__anonymous_block 
BEGIN P; END; 
* 
ERROR at line 1: 
ORA-01476: divisor is equal to zero 
ORA-0651...
value in "real world"
SQL> create or replace package PKG is 
2 procedure p; 
3 procedure p1; 
4 procedure p2; 
5 procedure p3; 
6 end; 
7 / 
Pac...
SQL> create or replace package body PKG is 
2 
3 procedure p is 
... 
19 
20 exception 
21 when others then 
22 for i in 1...
SQL> exec pkg.p3 
23-PKG.P 
32-PKG.P1 
33-PKG.P2 
34-PKG.P3 
1-__anonymous_block 
BEGIN pkg.p3; END; 
* 
ERROR at line 1: ...
did you miss it ?
SQL> exec pkg.p3 
23-PKG.P 
32-PKG.P1 
33-PKG.P2 
34-PKG.P3 
1-__anonymous_block 
BEGIN pkg.p3; END; 
subprogram !!! 
* 
E...
Feature 
inline PLSQL in SQL
every system ...
... I've worked on
struggles with case
no correlation :-)
SQL> select vendor 
2 from service_provider; 
VENDOR 
------------------------------ 
jones 
brown 
SMITH 
sigh...
"no problem.... I'll use initcap"
SQL> select initcap(vendor) 
2 from service_provider; 
INITCAP(VENDOR) 
------------------------------ 
Jones 
Brown 
Smit...
until ...
SQL> select initcap(vendor) 
2 from service_provider; 
INITCAP(VENDOR) 
------------------------------ 
Jones 
Brown 
Smit...
home grown
SQL> create or replace 
2 function my_initcap(p_string varchar2) return varchar2 is 
3 l_string varchar2(1000) := p_string...
cool ...
SQL> select my_initcap(vendor) 
2 from service_provider; 
MY_INITCAP(VENDOR) 
-------------------------- 
Jones 
Brown 
Sm...
until ...
"you stupid developer... 
don't call PLSQL from SQL !!!!"
SQL> select max(x) 
2 from ( 
3 select /*+ no_merge */ initcap(source) x 
4 from large_table 
5 ); 
... 
SQL> select max(x...
it can be done in SQL
SQL> select 
2 case 
3 when regexp_like(vendor,'(Mac[A-Z]|Mc[A-Z])') then vendor 
4 when vendor like '''%' then vendor 
5 ...
"Always code as if the person who 
ends up maintaining your code is a 
psychopathic killer who knows 
where you live." 
- ...
12c ... user defined functions
SQL> WITH 
2 function my_initcap(p_string varchar2) 
3 return varchar2 is 
4 l_string varchar2(1000) := p_string; 
5 begin...
multiple routines
SQL> WITH 
2 function is_scottish(p_string varchar2) return boolean is 
3 begin 
4 return regexp_like(p_string,'(Mac[A-Z]|...
note: 12c client
11.2 and below
SQL> WITH 
2 function my_initcap(p_string varchar2) return varchar2 is 
3 l_string varchar2(1000) := p_string; 
function m...
and a blast from the past :-)
SQL> create or replace 
2 procedure NAMES_PROCESSOR is 
3 cursor C is 
4 WITH 
5 function my_initcap(p_string varchar2) 
r...
SQL> create or replace 
2 procedure NAMES_PROCESSOR is 
3 rc sys_refcursor; 
4 begin 
5 open rc for 
6 q'{ WITH 
7 functio...
WITH_PLSQL 
unrelated to previous
DML (or complex SQL)
SQL> insert into CONTRACTS 
2 WITH 
3 function my_initcap(p_string varchar2) 
4 return varchar2 is 
5 l_string varchar2(10...
SQL> insert /*+ WITH_PLSQL */ into CONTRACTS 
2 WITH 
3 function my_initcap(p_string varchar2) 
4 return varchar2 is 
5 l_...
determinism
SQL> with 
2 function f return timestamp as 
3 begin 
4 return systimestamp; 
5 end; 
6 select f 
7 from dual 
8 connect b...
DETERMINISTIC keyword
SQL> with 
2 function f return timestamp DETERMINISTIC as 
3 begin 
4 return systimestamp; 
5 end; 
6 select f 
7 from dua...
conventional scalar caching
SQL> with 
2 function f return timestamp as 
3 begin 
4 return systimestamp; 
5 end; 
6 select ( select f from dual ) 
7 f...
are they really faster ?
SQL> create or replace 
2 function F return number is 
3 begin 
4 return 1; 
5 end; 
6 / 
Function created.
SQL> select sum(f) 
2 from 
3 ( select level from dual 
4 connect by level <= 1000 ), 
5 ( select level from dual 
6 conne...
SQL> with 
2 function f1 return number is 
3 begin 
4 return 1; 
5 end; 
6 select sum(f1) 
7 from 
8 ( select level from d...
"but what about all my PLSQL !!!"
SQL> create or replace 
2 function F return number is 
3 pragma udf; 
4 begin 
5 return 1; 
6 end; 
SQL> select sum(f) 
2 ...
Feature 
top-n simplifications 
308
"5 most recently hired employees" 
309
SQL> select empno, ename, hiredate 
2 from scott.emp 
3 where rownum <= 5 
4 order by hiredate desc; 
EMPNO ENAME HIREDATE...
inline view 
311
SQL> select * 
2 from ( 
3 select empno, ename, hiredate 
4 from scott.emp 
5 order by hiredate desc 
6 ) 
7 where rownum ...
------------------------------------------------ 
| Id | Operation | Name | Rows | 
--------------------------------------...
SQL> select * 
2 from ( 
3 select 
4 empno, ename, hiredate, 
5 row_number() over ( order by hiredate desc) rn 
6 from sco...
------------------------------------------------- 
| Id | Operation | Name | Rows | 
-------------------------------------...
12c .... "easier" 
316
SQL> select empno, ename, hiredate 
2 from scott.emp 
3 order by hiredate desc 
4 fetch first 2 rows only; 
EMPNO ENAME HI...
behind the scenes 
318
------------------------------------------------- 
| Id | Operation | Name | Rows | 
-------------------------------------...
variations 
320
SQL> select empno, ename, hiredate 
2 from scott.emp 
3 order by hiredate desc 
4 fetch first 1 row only; 
EMPNO ENAME HIR...
SQL> select empno, ename, hiredate 
2 from scott.emp 
3 order by hiredate desc 
4 fetch first 5 row only; 
EMPNO ENAME HIR...
SQL> select empno, ename, hiredate 
2 from scott.emp 
3 order by hiredate desc 
4 fetch first 10 percent rows only; 
EMPNO...
pagination 
324
SQL> select empno, ename, hiredate 
2 from scott.emp 
3 order by hiredate desc 
4 offset 5 rows fetch next 3 rows only; 
E...
idiosyncracies 
326
SQL> select empno, ename, hiredate 
2 from scott.emp 
3 order by hiredate desc 
4 fetch LAST 5 rows only; 
fetch LAST 5 ro...
SQL> select * 
2 from ( 
3 select empno, ename, hiredate 
4 from scott.emp 
5 order by hiredate asc 
6 fetch first 5 rows ...
no percent pagination 
329
SQL> select empno, ename, hiredate 
2 from scott.emp 
3 order by hiredate desc 
4 offset 20 percent fetch 
5 next 10 perce...
plsql quirk 
331
"Note that in real life, 
you would use bind variables 
instead of hard-coded literals" 
332 
- Tom Kyte, 
Oracle Magazine...
SQL> declare 
2 l_num number := 5; 
3 begin 
4 for i in ( 
5 select empno, ename, hiredate 
6 from scott.emp 
7 order by h...
SQL> declare 
2 l_num number := 5; 
3 begin 
4 for i in ( 
5 select empno, ename, hiredate 
6 from scott.emp 
7 order by h...
Feature 
adaptive plans
SQL> create table PARENT ( p int, pdata varchar2(20) ); 
Table created. 
SQL> create table CHILD ( c int, p int, cdata cha...
SQL> exec dbms_stats.gather_table_stats('','PARENT') 
PL/SQL procedure successfully completed. 
SQL> exec dbms_stats.gathe...
SQL> set autotrace traceonly explain 
SQL> select * 
2 from PARENT p, 
3 CHILD c 
4 where p.p < 10 
5 and p.p = c.p; 
----...
now lets mess with it
SQL> insert into PARENT 
2 select mod(rownum,5)*2+1, rownum 
3 from dual 
4 connect by level <= 20000; 
20000 rows created...
a new cursor
SQL> select /*+ gather_plan_statistics */ * 
2 from CHILD c, 
3 PARENT p 
4 where p.p < 10 
5 and p.p = c.p; 
no rows sele...
----------------------------------------------------------- 
| Id | Operation | Name | 
----------------------------------...
----------------------------------------------------------- 
| Id | Operation | Name | 
----------------------------------...
----------------------------------------------------------- 
| Id | Operation | Name | 
----------------------------------...
----------------------------------------------------------- 
| Id | Operation | Name | 
----------------------------------...
SQL> select * 
2 from table( 
3 dbms_xplan.display_cursor( 
4 null,null,'ALLSTATS LAST')); 
------------------------------...
just be aware
tools will (hopefully) catch up
Feature 
pattern matching 
350
analytics ... since 8.1.6 
351 
median 
top n 
moving average 
etc
"analysis" 
often 
"patterns" 
352
real example 
353
354
355
AML 
356 
anti money laundering
"Find 10 consecutive deposits in a 
24 hour period, then 
a withdrawal within three days of 
the last deposit, at a differ...
ACCT TSTAMP WTHD_TSTAMP TYPE AMT 
---------- ------------------ ------------------ ---- ------- 
54261 25/01/13 17:20:55 D...
hard... with analytics 
359
12c 
360
pattern matching 
361
SQL> select acct, tstamp, wthd_tstamp, txn_type, amt 
2 from account_txns 
3 MATCH_RECOGNIZE 
4 ( 
5 partition by acct 
6 ...
"What is the longest losing 
streak for customers since 
the start of the month" 
363
SQL> select acct, started_losing, finished_losing 
2 from account_txns 
3 MATCH_RECOGNIZE 
4 ( 
5 partition by acct 
6 ord...
ACCT STARTED_LOSING FINISHED_LOSING 
---------- ------------------- ------------------- 
66 01/02/2014 10:49:41 01/02/2014...
SQL> select acct, ceil(max(finished_losing-started_losing)) 
2 from account_txns 
3 MATCH_RECOGNIZE 
4 ( 
5 partition by a...
ACCT CEIL(MAX(FINISHED_LOSING-STARTED_LOSING)) 
---------- ----------------------------------------- 
66 3 
184 7 
280 2 
...
Feature 
scheduler enhancements 
368
external scripts 
369
SQL> declare 
2 l_job varchar2(100) := 
3 '#!/bin/ksh 
4 /bin/ps -ef > /tmp/process.out'; 
5 begin 
6 dbms_scheduler.creat...
# cat CDB12_j000_4559.trc 
[snip] 
ORA-12012: error on auto execute of job "SCOTT"."UNIX_PS" 
ORA-27451: CREDENTIAL_NAME c...
SQL> begin 
2 dbms_scheduler.create_credential( 
3 credential_name=>'MY_ACCT', 
4 username =>'unixacct', 
5 password =>'un...
SQL> declare 
2 l_job varchar2(100) := 
3 'connect / as sysdba 
4 spool /tmp/x.out 
5 select * from v$database; 
6 exit'; ...
Feature 
data redaction
SQL> desc ACCOUNTS 
Name Null? Type 
----------------------------- -------- ------------ 
ID NUMBER(8) 
NAME VARCHAR2(30) ...
SQL> begin 
2 dbms_redact.add_policy ( 
3 object_schema => user, 
4 object_name => 'ACCOUNTS', 
5 column_name => 'EMAIL_AD...
SQL> conn scott/tiger 
Connected. 
SQL> select * from ACCOUNTS; 
ID NAME EMAIL_ADDRESS 
-------- -------------------- ----...
378 
take care with clients
SQL> desc ACCOUNTS 
Name Null? Type 
----------------------------- -------- ------------ 
ID NUMBER(8) 
NAME VARCHAR2(30) ...
SQL> declare 
2 p_query varchar2(32767) 
3 := 'select * from mcdonac.accounts'; 
4 
5 l_cur int := dbms_sql.open_cursor; 
...
381 
take care with security
382
Feature 
join enhancements
11.2
SQL> create table scott.emp2 as 
2 select * from scott.emp; 
Table created. 
SQL> select * 
2 from scott.emp e, 
3 scott.e...
12c
SQL> select * 
2 from scott.emp e, 
3 scott.emp2 e2, 
4 scott.dept d 
5 where e.deptno = d.deptno(+) 
6 and e2.deptno = d....
correlated inline views
SQL> drop table scott.DEPT_BENEFITS purge; 
Table dropped. 
SQL> create table scott.DEPT_BENEFITS as 
2 select d.*, 10 ben...
SQL> select e.empno, e.deptno, d.benefits 
2 from scott.emp e, 
3 scott.dept_benefits d 
4 where e.deptno = d.deptno 
5 or...
"benefits for each employee"
SQL> select e.empno, d.deptno, b.benefits 
2 from scott.emp e, 
3 ( select benefits 
4 from scott.DEPT_BENEFITS d 
5 where...
CROSS APPLY
SQL> select e.empno, e.deptno, b.benefits 
2 from scott.emp e 
3 CROSS APPLY 
4 ( select benefits 
5 from scott.DEPT_BENEF...
"big deal"
SQL> select e.empno, d.deptno, b.benefits 
2 from scott.emp e, 
3 ( select benefits 
4 from scott.DEPT_BENEFITS d 
5 
wher...
"best benefit for each employee"
SQL> select e.empno, e.deptno, b.benefits 
2 from scott.emp e 
3 CROSS APPLY 
4 ( select benefits 
5 from scott.DEPT_BENEF...
399 
Feature 
anyone remember this ?
400 
11.2
401
402 
"version control"
403 
package PKG is 
select COL1, COL2 
from MY_VIEW 
package PKG(V2) is 
select COL1, NEW_COL 
from MY_VIEW(V2) 
both in ...
404 
"edition based redefinition"
405 
really cool .... but
406 
Enabling editions is 
global, 
retroactive 
and 
irreversible. 
- 11g2 doc
407 
SQL> alter user TO_BE_EDITIONED enable editions; 
alter user TO_BE_EDITIONED enable editions 
* 
ERROR at line 1: 
OR...
408 
12c
409 
much much better
410 
schema is editionable...
411 
...and object is editionable
wrap up 
412
12c 
413
414
Connor McDonald 
OracleDBA 
co.uk 
415
416 
ORA-03113 
@connor_mc_d 
connormcdonald.wordpress.com
OpenWorld Sep14 12c for_developers
OpenWorld Sep14 12c for_developers
OpenWorld Sep14 12c for_developers
OpenWorld Sep14 12c for_developers
OpenWorld Sep14 12c for_developers
OpenWorld Sep14 12c for_developers
OpenWorld Sep14 12c for_developers
OpenWorld Sep14 12c for_developers
OpenWorld Sep14 12c for_developers
OpenWorld Sep14 12c for_developers
You’ve finished this document.
Upcoming SlideShare
OakTable World Sep14 clonedb
Next
Upcoming SlideShare
OakTable World Sep14 clonedb
Next

3

Share

OpenWorld Sep14 12c for_developers

Slides from Openworld

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all

OpenWorld Sep14 12c for_developers

  1. 1. NOTE itty bitty fonts in this presentation SQL> exec sample_font Can you read this ? 1
  2. 2. Connor McDonald OracleDBA co.uk 2
  3. 3. 3
  4. 4. bio slide 5
  5. 5. gratuitous book plug 6
  6. 6. 7
  7. 7. gratuitous swim plug 8
  8. 8. 9
  9. 9. "why bother?" 10
  10. 10. 2013 2014 2015 2016 2017 2018 2019 2020 2021 12c 12.1.0.2 12.2 management visibility 12c desupported "pilot"
  11. 11. 1) know what’s coming 12
  12. 12. don’t reinvent
  13. 13. 15 2) there's a lot in 12c !
  14. 14. 16 but not widely advertised
  15. 15. 17 because ...
  16. 16. 18 blah blah multi tenant blah
  17. 17. 19 blah blah blah
  18. 18. 3) our use of the db is simpler 20
  19. 19. 21 Value DB mainframe client server web soa Code 1209018910123456789
  20. 20. <warning> </warning>
  21. 21. 25 @connor_mc_d connormcdonald.wordpress.com
  22. 22. 26 first impressions
  23. 23. 27
  24. 24. 28 SQL> create user DEV_TESTING 2 identified by MYPASS; create user DEV_TESTING identified by MYPASS * ERROR at line 1: ORA-65096: invalid common user or role name ?
  25. 25. 29 be patient
  26. 26. 30
  27. 27. 31 or let someone else do it
  28. 28. 32 http://www.oracle.com/technetwork/community/developer-vm/index.html
  29. 29. 33
  30. 30. 34 "Feature:" total recall
  31. 31. 35
  32. 32. 36 11g feature !
  33. 33. 37 why ?
  34. 34. 38 we've all done it...
  35. 35. 39 job to job to job...
  36. 36. 40 auditing row changes
  37. 37. 41 SQL> desc T Name Null? Type ----------------------------- -------- ------------- OWNER NOT NULL VARCHAR2(30) OBJECT_NAME NOT NULL VARCHAR2(30) SQL> desc T_AUDIT Name Null? Type ----------------------------- -------- -------------- AUDIT_DATE DATE AUDIT_ACTION VARCHAR2(1) OWNER NOT NULL VARCHAR2(30) OBJECT_NAME NOT NULL VARCHAR2(30)
  38. 38. 42 SQL> create or replace 2 trigger AUDIT_TRG 3 after insert or update or delete on T 4 for each row 5 declare 6 v_action varchar2(1) := case when updating then 'U' 7 when deleting then 'D' else 'I' end; 8 begin 9 if updating or inserting then 10 insert into T_AUDIT 11 values (sysdate 12 ,v_action 13 ,:new.owner 14 ,:new.object_name); 15 else 16 insert into T_AUDIT 17 values (sysdate 18 ,v_action 19 ,:old.owner 20 ,:old.object_name); 21 end if; 22 end; 23 / Trigger created.
  39. 39. 43 works but slow...
  40. 40. 44 SQL> insert into T 2 select owner, object_name 3 from all_objects 4 where rownum <= 10000; INSERT INTO T_AUDIT VALUES (SYSDATE ,:B3 ,:B1 ,:B2 ) 10000 rows created. call count cpu elapsed disk query current ------- ------ ------- ---------- -------- --------- ---------- Parse 1 0.00 0.00 0 0 0 Execute 10000 0.79 0.97 2 109 10845 Fetch 0 0.00 0.00 0 0 0 ------- ------ ------- ---------- -------- --------- ---------- total 10001 0.79 0.97 2 109 10845
  41. 41. 45 if you were diligent
  42. 42. 46 bulk binding
  43. 43. 47 create or replace package T_PKG is type each_row is record ( action varchar2(1), owner varchar2(30), object_name varchar2(30) ); type row_list is table of each_row index by pls_integer; g row_list; end; /
  44. 44. 48 create or replace trigger AUDIT_TRG1 before insert or update or delete on T begin t_pkg.g.delete; end; /
  45. 45. 49 create or replace trigger AUDIT_TRG2 after insert or update or delete on T for each row begin if updating or inserting then t_pkg.g(t_pkg.g.count+1).owner := :new.owner; t_pkg.g(t_pkg.g.count).object_name := :new.object_name; else t_pkg.g(t_pkg.g.count).owner := :old.owner; t_pkg.g(t_pkg.g.count).object_name := :old.object_name; end if; end; /
  46. 46. 50 create or replace trigger AUDIT_TRG3 after insert or update or delete on T declare v_action varchar2(1) := case when updating then 'U' when deleting then 'D' else 'I' end; begin forall i in 1 .. t_pkg.g.count insert into T_AUDIT values ( sysdate, v_action, t_pkg.g(i).owner, t_pkg.g(i).object_name); t_pkg.g.delete; end; /
  47. 47. 51 SQL> insert into T 2 select owner, object_name 3 from all_objects 4 where rownum <= 10000; INSERT INTO T_AUDIT VALUES ( SYSDATE, :B1 , :B2 , :B3 ) 10000 rows created. call count cpu elapsed disk query current ------- ------ ------- --------- -------- ---------- ---------- Parse 1 0.00 0.00 0 0 0 Execute 1 0.04 0.03 0 90 478 Fetch 0 0.00 0.00 0 0 0 ------- ------ ------- --------- -------- ---------- ---------- total 2 0.04 0.03 0 90 478
  48. 48. 52 compound trigger 11g
  49. 49. but ... 53
  50. 50. a better, faster, robust version ... 54
  51. 51. ... total recall 11g 55
  52. 52. SQL> create tablespace SPACE_FOR_ARCHIVE 2 datafile 'C:ORACLEDB11ARCH_SPACE.DBF' 3 size 100M; Tablespace created. 56
  53. 53. SQL> CREATE FLASHBACK ARCHIVE longterm 2 TABLESPACE space_for_archive 3 RETENTION 1 YEAR; Flashback archive created. 57
  54. 54. SQL> ALTER TABLE EMP FLASHBACK ARCHIVE LONGTERM; Table altered. 58
  55. 55. SQL> select * from EMP; -------------------------------------------------- | Id | Operation | Name | Rows | Bytes | -------------------------------------------------- | 0 | SELECT STATEMENT | | 14 | 518 | | 1 | TABLE ACCESS FULL| EMP | 14 | 518 | -------------------------------------------------- 59
  56. 56. [after DML and time passing] SQL> select * from EMP 2 AS OF TIMESTAMP SYSDATE-365; ----------------------------------------------------------------- | Id | Operation | Name | Rows | ----------------------------------------------------------------- | 0 | SELECT STATEMENT | | 446 | | 1 | VIEW | | 446 | | 2 | UNION-ALL | | | |* 3 | FILTER | | | | 4 | PARTITION RANGE ITERATOR| | 445 | |* 5 | TABLE ACCESS FULL | SYS_FBA_HIST_69539 | 445 | |* 6 | FILTER | | | |* 7 | HASH JOIN OUTER | | 1 | |* 8 | TABLE ACCESS FULL | EMP | 1 | |* 9 | TABLE ACCESS FULL | SYS_FBA_TCRV_69539 | 14 | ------------------------------------------------------------------ 60
  57. 57. SQL> select table_name 2 from user_tables 3 / TABLE_NAME --------------------------- SYS_FBA_HIST_71036 SYS_FBA_TCRV_71036 SYS_FBA_DDL_COLMAP_71036 EMP 61
  58. 58. "I don't need to look back in time..." 62
  59. 59. but can also be your audit ! 63
  60. 60. SQL> alter table EMP add 2 CREATE_TS timestamp default systimestamp; SQL> update EMP 2 set sal = sal*10 3 where empno = 7369; SQL> delete from EMP 2 where empno = 7934; SQL> update EMP 2 set job = 'SALES' 3 where ename = 'SMITH'; SQL> update EMP 2 set comm = 1000 3 where empno = 7369; SQL> commit; 64
  61. 61. SQL> select empno, ename, job, sal, comm, 2 nvl(VERSIONS_STARTTIME,CREATE_TS) TS 3 ,nvl(VERSIONS_OPERATION,'I') OP 4 from EMP 5 versions between timestamp 6 timestamp '2014-02-11 20:12:00' and 7 systimestamp 8 order by empno; EMPNO ENAME JOB SAL COMM TS OP ---------- ---------- --------- ---------- ---------- ------------ -- 7369 SMITH CLERK 806 08.10.51 PM I 7369 SMITH SALES 8060 1000 08.12.10 PM U 7499 ALLEN SALESMAN 1606 300000000 08.10.51 PM I 7521 WARD SALESMAN 1256 500000000 08.10.51 PM I 7566 JONES MANAGER 2981 08.10.51 PM I 7900 JAMES CLERK 956 08.10.51 PM I 7902 FORD ANALYST 3006 08.10.51 PM I 7934 MILLER CLERK 1306 08.10.51 PM I 7934 MILLER CLERK 1306 08.12.10 PM D ... 65
  62. 62. so why didn't we ? 66
  63. 63. reason 1 67
  64. 64. separately licensed :-( 69
  65. 65. can 12c help ? 70
  66. 66. rebadged 71
  67. 67. flashback data archive 72
  68. 68. free ! 73
  69. 69. let 74 me repeat
  70. 70. oracle feature that is free ! 75
  71. 71. basis versus advanced 76
  72. 72. compression choose your cost 77 partitioning
  73. 73. reason 2 78
  74. 74. "yeah...but who ? where ? how ?" 79
  75. 75. SQL> alter table EMP add UPDATED_BY varchar2(10); Table altered. SQL> alter table EMP add UPDATED_PGM varchar2(10); Table altered. [etc] [etc] 80
  76. 76. can 12c help ? 81
  77. 77. context extension 82
  78. 78. SQL> begin 2 dbms_flashback_archive.set_context_level( 3 level=> 'ALL'); 4 end; PL/SQL procedure successfully completed. 83
  79. 79. SQL> update EMP 2 set sal = sal*10 3 where empno = 7499; 1 row updated. SQL> commit; 84
  80. 80. SQL> select XID from SYS_FBA_HIST_510592; XID ---------------- 09000B00C7080000 85
  81. 81. SQL> set serverout on SQL> begin 2 dbms_output.put_line( 3 dbms_flashback_archive.get_sys_context ( 4 '09000B00C7080000', 'USERENV', 'SESSION_USER')); 5 6 dbms_output.put_line( 7 dbms_flashback_archive.get_sys_context ( 8 '09000B00C7080000', 'USERENV', 'HOST')); 9 10 dbms_output.put_line( 11 dbms_flashback_archive.get_sys_context ( 12 '09000B00C7080000', 'USERENV', 'MODULE')); 13 end; 14 / SCOTT WORKGROUPXPS SQL*Plus 86
  82. 82. 87
  83. 83. SQL> desc SYS.SYS_FBA_CONTEXT_AUD Name Null? Type ------------------------- -------- ------------------ XID RAW(8) ACTION VARCHAR2(256) AUTHENTICATED_IDENTITY VARCHAR2(256) CLIENT_IDENTIFIER VARCHAR2(256) CLIENT_INFO VARCHAR2(256) CURRENT_EDITION_NAME VARCHAR2(256) CURRENT_SCHEMA VARCHAR2(256) CURRENT_USER VARCHAR2(256) DATABASE_ROLE VARCHAR2(256) DB_NAME VARCHAR2(256) GLOBAL_UID VARCHAR2(256) HOST VARCHAR2(256) IDENTIFICATION_TYPE VARCHAR2(256) INSTANCE_NAME VARCHAR2(256) IP_ADDRESS VARCHAR2(256) MODULE VARCHAR2(256) OS_USER VARCHAR2(256) SERVER_HOST VARCHAR2(256) SERVICE_NAME VARCHAR2(256) 88
  84. 84. SQL> @pt "select * from SYS.SYS_FBA_CONTEXT_AUD where xid = '09000B00C7080000'" XID : 09000B00C7080000 AUTHENTICATED_IDENTITY : scott CLIENT_IDENTIFIER : CLIENT_INFO : CURRENT_EDITION_NAME : ORA$BASE CURRENT_SCHEMA : SYS CURRENT_USER : SYS DATABASE_ROLE : PRIMARY DB_NAME : np12 HOST : WORKGROUPXPS IDENTIFICATION_TYPE : LOCAL INSTANCE_NAME : np12 MODULE : SQL*Plus OS_USER : xpshamcdc SERVER_HOST : xps SERVICE_NAME : SYS$USERS SESSION_EDITION_NAME : ORA$BASE SESSION_USER : SCOTT SESSION_USERID : 103 SESSIONID : 230698 TERMINAL : XPS 89
  85. 85. SQL> select empno, ename, job, sal, comm, 2 VERSIONS_XID 3 from EMP 4 versions between timestamp 5 timestamp '2014-02-11 20:12:00' and systimestamp 6 order by empno; EMPNO ENAME JOB SAL COMM VERSIONS_XID ---------- ---------- --------- ---------- ---------- ---------------- 7369 SMITH CLERK 806 7369 SMITH SALES 8060 1000 09001C00E04A0000 7499 ALLEN CLERK 16060 300000000 0A000A0024080000 7499 ALLEN SALESMAN 16060 300000000 09000B00C7080000 7499 ALLEN SALESMAN 1606 300000000 7521 WARD SALESMAN 1256 500000000 90
  86. 86. SQL> select ... 2 from 3 ( select 4 empno, ename, job, 5 sal, comm, VERSIONS_XID 6 from EMP 7 versions between timestamp 8 timestamp '2014-02-11 20:12:00' and 9 systimestamp 10 ) e, SYS.SYS_FBA_CONTEXT_AUD a 11 where e.VERSIONS_XID = a.XID; 91
  87. 87. so think about “total recall” 92 free in 11.2.0.4 as well
  88. 88. secure read only 93
  89. 89. efficient fdba 94
  90. 90. all your history... 95
  91. 91. all your audit... 96
  92. 92. be careful... silent errors 97
  93. 93. SQL> ALTER TABLE EMP FLASHBACK ARCHIVE LONGTERM; Table altered. Flashback Archive: Error ORA-1950 in SQL create table "SCOTT".SYS_FBA_DDL_COLMAP_91938 (STARTSCN NUMBER, ENDSCN NUMBER... Flashback Archive: Error ORA-942 in SQL insert into "SCOTT".SYS_FBA_DDL_COLMAP_91938 (ENDSCN, COLUMN_NAME, TYPE, ... Flashback Archive: Error ORA-942 in SQL "select count(*) from "SCOTT".SYS_FBA_DDL_COLMAP_91938" 98
  94. 94. data in the past ...
  95. 95. ... to data at "any" time
  96. 96. Feature temporal validity
  97. 97. wtf
  98. 98. very common
  99. 99. "when" is a row valid
  100. 100. SQL> CREATE TABLE emp_temporal ( 2 empno NUMBER, 3 name VARCHAR2(30), 4 sal NUMBER, 5 deptno NUMBER, 6 start_dt DATE, 7 end_dt DATE, 8 9 ); Table created.
  101. 101. 12c part of the definition
  102. 102. SQL> CREATE TABLE emp_temporal ( 2 empno NUMBER, 3 name VARCHAR2(30), 4 sal NUMBER, 5 deptno NUMBER, 6 start_dt DATE, 7 end_dt DATE, 8 PERIOD FOR valid_range (start_dt, end_dt) 9 ); Table created.
  103. 103. examples
  104. 104. SQL> select * from emp_temporal 2 order by empno, start_dt; EMPNO NAME SAL DEPTNO START_DT END_DT ---------- --------- ---------- ---------- --------- --------- 7369 SMITH 806 20 01-JAN-14 01-MAR-14 7369 SMYTH 806 21 02-MAR-14 01-SEP-14 7369 SMYTH 950 21 02-SEP-14 01-OCT-14 7499 ALLEN 1606 30 01-JAN-14 01-MAR-14 7521 WARD 1256 30 01-JAN-14 01-MAR-14 7566 JONES 2981 20 01-JAN-14 01-MAR-14 7654 MARTIN 1256 30 01-JAN-14 01-MAR-14 7698 BLAKE 2856 30 01-JAN-14 01-MAR-14
  105. 105. SQL> select * from emp_temporal 2 as of period for valid_range '01-FEB-14'; EMPNO NAME SAL DEPTNO START_DT END_DT ---------- --------- --------- ---------- --------- -------- 7369 SMITH 806 20 01-JAN-14 01-MAR-14 7499 ALLEN 1606 30 01-JAN-14 01-MAR-14 7521 WARD 1256 30 01-JAN-14 01-MAR-14 7566 JONES 2981 20 01-JAN-14 01-MAR-14 7654 MARTIN 1256 30 01-JAN-14 01-MAR-14
  106. 106. so what's happening ?
  107. 107. another new feature
  108. 108. what is the real query 113
  109. 109. 114 SQL> set autotrace traceonly stat SQL> select * from MY_VIEW 2 where CREATED > sysdate Statistics ------------------------------------------ 651 recursive calls 0 db block gets 2243 consistent gets 24 physical reads
  110. 110. 115 SQL> variable c clob SQL> begin 2 dbms_utility.expand_sql_text 3 ( 'select * from MY_VIEW'|| 4 'where created > sysdate',:c); 5 end; 6 / PL/SQL procedure successfully completed. SQL> print c
  111. 111. 116 SQL> create or replace 2 view MY_VIEW as 3 select 4 o.owner, 5 o.created, 6 s.bytes, 7 s.tablespace_name 8 from 9 dba_segments s, 10 all_objects o 11 where o.owner = s.owner 12 and o.object_name = s.segment_name; View created.
  112. 112. 117 SELECT "A1"."OWNER" "OWNER", "A1"."NAME" "NAME", "A1"."CREATED" "CREATED", "A1"."BYTES" "BYTES", "A1"."TABLESPACE_NAME" "TABLESPACE_NAME" FROM (SELECT "A2"."OWNER" "OWNER", "A2"."OBJECT_NAME" "NAME", "A2"."CREATED" "CREATED", "A3"."BYTES" "BYTES", "A3"."TABLESPACE_NAME" "TABLESPACE_NAME" FROM (SELECT "A4" ."OWNER" "OWNER", "A4"."SEGMENT_NAME" "SEGMENT_NAME", "A4"."PARTITION_NAME" "PARTITION_NAME", "A4"."SEGMENT_TYPE" "SEGMENT_TYPE", "A4"."SEGMENT_SUBTYPE" "SEGMENT_SUBTYPE", "A4"."TABLESPACE_NAME" "TABLESPACE_NAME", "A4"."HEADER_FILE" "HEADER_FILE", "A4"."HEADER_BLOCK" "HEADER_BLOCK", DECODE(BITAND("A4"."SEGMENT_FLAGS",131072),131072, "A4"."BLOCKS",DECODE(BITAND("A4"."SEGMENT_FLAGS",1),1, "SYS"."DBMS_SPACE_ADMIN"."SEGMENT_NUMBER_BLOCKS"("A4"."TABLESPACE_ID", "A4"."RELATIVE_FNO", "A4"."HEADER_BLOCK", "A4"."SEGMENT_TYPE_ID", "A4"."BUFFER_POOL_ID", "A4"."SEGMENT_FLAGS", "A4"."SEGMENT_OBJD", "A4"."BLOCKS"), "A4"."BLOCKS"))*"A4"."BLOCKSIZE" "BYTES", DECODE(BITAND("A4"."SEGMENT_FLAGS",131072),131072, "A4"."BLOCKS",DECODE(BITAND("A4"."SEGMENT_FLAGS",1),1, "SYS"."DBMS_SPACE_ADMIN"."SEGMENT_NUMBER_BLOCKS"("A4"."TABLESPACE_ID", "A4"."RELATIVE_FNO",
  113. 113. 118 "A4"."HEADER_BLOCK", "A4"."SEGMENT_TYPE_ID", "A4"."BUFFER_POOL_ID", "A4"."SEGMENT_FLAGS", "A4"."SEGMENT_OBJD", "A4"."BLOCKS"), "A4"."BLOCKS")) "BLOCKS",DECODE(BITAND("A4"."SEGMENT_FLAGS",131072),131072, "A4"."EXTENTS",DECODE(BITAND("A4"."SEGMENT_FLAGS",1),1, "SYS"."DBMS_SPACE_ADMIN"."SEGMENT_NUMBER_EXTENTS"("A4"."TABLESPACE_ID", "A4"."RELATIVE_FNO", "A4"."HEADER_BLOCK", "A4"."SEGMENT_TYPE_ID", "A4"."BUFFER_POOL_ID", "A4"."SEGMENT_FLAGS", "A4"."SEGMENT_OBJD", "A4"."EXTENTS"), "A4"."EXTENTS")) "EXTENTS", "A4"."INITIAL_EXTENT" "INITIAL_EXTENT", "A4"."NEXT_EXTENT" "NEXT_EXTENT", "A4"."MIN_EXTENTS" "MIN_EXTENTS", "A4"."MAX_EXTENTS" "MAX_EXTENTS", "A4"."MAX_SIZE" "MAX_SIZE", "A4"."RETENTION" "RETENTION", "A4"."MINRETENTION" "MINRETENTION", "A4"."PCT_INCREASE" "PCT_INCREASE", "A4"."FREELISTS" "FREELISTS", "A4"."FREELIST_GROUPS" "FREELIST_GROUPS", "A4"."RELATIVE_FNO" "RELATIVE_FNO", DECODE("A4"."BUFFER_POOL_ID",1,'KEEP',2,'RECYCLE','DEFAULT') "BUFFER_POOL", DECODE("A4"."FLASH_CACHE",1,'KEEP',2, 'NONE','DEFAULT') "FLASH_CACHE",DECODE("A4"."CELL_FLASH_CACHE",1,'KEEP',2,'NONE','DEFAULT') "CELL_FLASH_CACHE" FROM ( (SELECT NVL("A199"."NAME",'SYS') "OWNER", "A198"."NAME" "SEGMENT_NAME",
  114. 114. 119 "A198"."SUBNAME" "PARTITION_NAME", "A196"."OBJECT_TYPE" "SEGMENT_TYPE", "A195"."TYPE#" "SEGMENT_TYPE_ID",DECODE(BIT AND("A195"."SPARE1",2097408),2097152,'SECUREFILE',256,'ASSM','MSSM') "SEGMENT_SUBTYPE", "A197"."TS#" "TABLESPACE_ID", "A197"."NAME" "TABLESPACE_NAME", "A197"."BLOCKSIZE" "BLOCKSIZE", "A194"."FILE#" "HEADER_FILE", "A195"."BLOCK#" "HEADER_BLOCK", "A195"."BLOCKS"*"A197"."BLOCKSIZE" "BYTES", "A195"."BLOCKS" "BLOCKS", "A195"."EXTENTS" "EXTENTS", "A195"."INIEXTS"*"A197"."BLOCKSIZE" "INITIAL_EXTENT", "A195"."EXTSIZE"*"A197"."BLOCKSIZE" "NEXT_EXTENT", "A195"."MINEXTS" "MIN_EXTENTS", "A195"."MAXEXTS" "MAX_EXTENTS",DECODE(BITAND("A195"."SPARE1",4194304),4194304, "A195"."BITMAPRANGES",NULL) "MAX_SIZE",TO_CHAR(DECODE( BITAND("A195"."SPARE1",2097152),2097152, DECODE("A195"."LISTS",0,'NONE',1,'AUTO',2,'MIN',3,'MAX',4,'DEFAULT','INVALID'),N ULL)) "RETENTION",DECODE(BITAND("A195"."SPARE1",2097152),2097152, "A195"."GROUPS",NULL) "MINRETENTION",DECODE(BITAND("A197"."FLAGS",3),1,TO_NUMBER(NULL), "A195"."EXTPCT") "PCT_INCREASE",DECODE(BITAND("A197"."FLAGS",32),32, TO_NUMBER(NULL),DECODE("A195"."LISTS",0,1, "A195"."LISTS")) "FREELISTS",DECODE(BITAND("A197"."FLAGS",32),32,TO_NUMBER(NULL),DECODE("A195"."G ROUPS",0,1, "A195"."GROUPS")) "FREELIST_GROUPS", "A195"."FILE#" "RELATIVE_FNO",BITAND("A195"."CACHEHINT",3) "BUFFER_POOL_ID", BITAND("A195"."CACHEHINT",12)/4 "FLASH_CACHE",BITAND("A195"."CACHEHINT",48)/16 "CELL_FLASH_CACHE", NVL("A195"."SPARE1",0) "SEGMENT_FLAGS",DECODE(BITAND("A195"."SPARE1",1),1, "A195"."HWMINCR", "A198"."DATAOBJ#") "SEGMENT_OBJD" FROM "SYS"."USER$" "A199", "SYS"."OBJ$" "A198", "SYS"."TS$" "A197", ( (SELECT
  115. 115. 120 DECODE(BITAND("A209"."PROPERTY",8192),8192,'NESTED TABLE','TABLE') "OBJECT_TYPE", 2 "OBJECT_TYPE_ID",5 "SEGMENT_TYPE_ID", "A209"."OBJ#" "OBJECT_ID", "A209"."FILE#" "HEADER_FILE", "A209"."BLOCK#" "HEADER_BLOCK", "A209"."TS#" "TS_NUMBER" FROM "SYS"."TAB$" "A209" WHERE BITAND("A209"."PROPERTY",1024)=0) UNI ON ALL (SELECT 'TABLE PARTITION' "OBJECT_TYPE",19 "OBJECT_TYPE_ID",5 "SEGMENT_TYPE_ID", "A208"."OBJ#" "OBJECT_ID", "A208"."FILE#" "HEADER_FILE", "A208"."BLOCK#" "HEADER_BLOCK", "A208"."TS#" "TS_NUMBER" FROM "SYS"."TABPART$" "A208") UNION ALL (SELECT 'CLUSTER' "OBJECT_TYPE",3 "OBJECT_TYPE_ID",5 "SEGMENT_TYPE_ID", "A207"."OBJ#" "OBJECT_ID", "A207"."FILE#" "HEADER_FILE", "A207"."BLOCK#" "HEADER_BLOCK", "A207"."TS#" "TS_NUMBER" FROM "SYS"."CLU$" "A207") UNION ALL (SELECT DECODE("A206"."TYPE#",8,'LOBINDEX','INDEX') "OBJECT_TYPE",1 "OBJECT_TYPE_ID",6 "SEGMENT_TYPE_ID", "A206"."OBJ#" "OBJECT_ID", "A206"."FILE#" "HEADER_FILE", "A206"."BLOCK#" "HEADER_BLOCK", "A206"."TS#" "TS_NUMBER" FROM "SYS"."IND$" "A206" WHERE "A206"."TYPE#"=1 OR "A206"."TYPE#"=2 OR "A206"."TYPE#"=3 OR "A206"."TYPE#"=4 OR "A206"."TYPE#"=6 OR "A206"."TYPE#"=7 OR "A206"."TYPE#"=8 OR "A206"."TYPE#"=9) UNION ALL (SELECT 'INDEX PARTITION' "OBJECT_TYPE",20 "OBJECT_TYPE_ID",6 "SEGMENT_TYPE_ID", "A205"."OBJ#" "OBJECT_ID", "A205"."FILE#" "HEADER_FILE", "A205"."BLOCK#" "HEADER_BLOCK",
  116. 116. 121 "A205"."TS#" "TS_NUMBER" FROM "SYS"."INDPART$" "A205") UNION ALL (SELECT 'LOBSEGMENT' "OBJECT_TYPE",21 "OBJECT_TYPE_ID",8 "SEGMENT_TYPE_ID", "A204"."LOBJ#" "OBJECT_ID", "A204"."FILE#" "HEADER_FILE", "A204"."BLOCK#" "HEADER_BLOCK", "A204"."TS#" "TS_NUMBER" FROM "SYS"."LOB$" "A204" WHERE BITAND("A204"."PROPERTY",64)=0 OR BITAND("A204"."PROPERTY",128)=128) UNION ALL (SELECT 'TABLE SUBPARTITION' "OBJECT_TYPE",34 "OBJECT_TYPE_ID",5 "SEGMENT_TYPE_ID", "A203"."OBJ#" "OBJECT_ID", "A203"."FILE#" "HEADER_FILE", "A203"."BLOCK#" "HEADER_BLOCK", "A203"."TS#" "TS_NUMBER" FROM "SYS"."TABSUBPART$" "A203") UNION ALL (SELECT 'INDEX SUBPARTITION' "OBJECT_TYPE",35 "OBJECT_TYPE_ID",6 "SEGMENT_TYPE_ID", "A202"."OBJ#" "OBJECT_ID", "A202"."FILE#" "HEADER_FILE", "A202"."BLOCK#" "HEADER_BLOCK", "A202"."TS#" "TS_NUMBER" FROM "SYS"."INDSUBPART$" "A202") UNION ALL (SELECT DECODE("A201"."FRAGTYPE$",'P','LOB PARTITION','LOB SUBPARTITION') "OBJECT_TYPE",DECODE("A201"."FRAGTYPE$",'P',40,41) "OBJECT_TYPE_ID",8 "SEGMENT_TYPE_ID", "A201"."FRAGOBJ#" "OBJECT_ID", "A201"."FILE#" "HEADER_FILE", "A201"."BLOCK#" "HEADER_BLOCK", "A201"."TS#" "TS_NUMBER" FROM "SYS"."LOBFRAG$" "A201")) "A196", "SYS"."SEG$" "A195", "SYS"."FILE$" "A194" WHERE "A195"."FILE#"="A196"."HEADER_FILE" AND "A195"."BLOCK#"="A196"."HEADER_BLOCK" AND "A195"."TS#"="A196"."TS_NUMBER" AND "A195"."TS#"="A197"."TS#" AND "A198"."OBJ#"="A196"."OBJECT_ID" AND "A198"."OWNER#"="A199"."USER#"(+) AND "A195"."TYPE#"="A196"."SEGMENT_TYPE_ID" AND "A198"."TYPE#"="A196"."OBJECT_TYPE_ID" AND "A195"."TS#"="A194"."TS#" AND
  117. 117. 122 "A195"."FILE#"="A194"."RELFILE#") UNION ALL (SELECT NVL("A193"."NAME",'SYS') "OWNER", "A191"."NAME" "SEGMENT_NAME",NULL "PARTITION_NAME", DECODE("A190"."TYPE#",1,'ROLLBACK',10,'TYPE2 UNDO') "SEGMENT_TYPE", "A190"."TYPE#" "SEGMENT_TYPE_ID",NULL "SEGMENT_SUBTYPE", "A192"."TS#" "TABLESPACE_ID", "A192"."NAME" "TABLESPACE_NAME", "A192"."BLOCKSIZE" "BLOCKSIZE", "A189"."FILE#" "HEADER_FILE", "A190"."BLOCK#" "HEADER_BLOCK", "A190"."BLOCKS"*"A192"."BLOCKSIZE" "BYTES", "A190"."BLOCKS" "BLOCKS", "A190"."EXTENTS" "EXTENTS", "A190"."INIEXTS"*"A192"."BLOCKSIZE" "INITIAL_EXTENT", "A190"."EXTSIZE"*"A192"."BLOCKSIZE" "NEXT_EXTENT", "A190"."MINEXTS" "MIN_EXTENTS", "A190"."MAXEXTS" "MAX_EXTENTS",DECODE(BITAND("A190"."SPARE1",4194304),4194304, "A190"."BITMAPRANGES",NULL) "MAX_SIZE",NULL "RETENTION",NULL "MINRETENTION", "A190"."EXTPCT" "PCT_INCREASE",DECODE(BITAND("A192"."FLAGS",32),32,TO_NUMBER(NULL),DECODE("A190" ."LISTS",0,1, "A190"."LISTS")) "FREELISTS",DECODE(BITAND("A192"."FLAGS",32),32,TO_NUMBER(NULL), DECODE("A190"."GROUPS",0,1,"A190"."GROUPS")) "FREELIST_GROUPS", "A190"."FILE#" "RELATIVE_FNO",BITAND("A190"."CACHEHINT",3) "BUFFER_POOL_ID",BITAND("A190"."CACHEHINT",12)/4 "FLASH_CACHE", BITAND("A190"."CACHEHINT",48)/16 "CELL_FLASH_CACHE",NVL("A190"."SPARE1",0) "SEGMENT_FLAGS", "A191"."US#" "SEGMENT_OBJD" FROM "SYS"."USER$" "A193","SYS"."TS$" "A192", "SYS"."UNDO$" "A191", "SYS"."SEG$" "A190", "SYS"."FILE$" "A189" WHERE "A190"."FILE#"="A191"."FILE#" AND "A190"."BLOCK#"="A191"."BLOCK#" AND "A190"."TS#"="A191"."TS#" AND "A190"."TS#"="A192"."TS#" AND "A190"."USER#"="A193"."USER#"(+) AND ("A190"."TYPE#"=1 OR "A190"."TYPE#"=10) AND "A191"."STATUS$"<>1 AND
  118. 118. 123 "A191"."TS#"="A189"."TS#" AND "A191"."FILE#"="A189"."RELFILE#") UNION ALL (SELECT NVL("A188"."NAME",'SYS') "OWNER", TO_CHAR("A185"."FILE#")||'.'||TO_CHAR("A186"."BLOCK#") "SEGMENT_NAME",NULL "PARTITION_NAME", DECODE("A186"."TYPE#",2,'DEFERRED ROLLBACK',3, 'TEMPORARY',4,'CACHE',9,'SPACE HEADER','UNDEFINED') "SEGMENT_TYPE", "A186"."TYPE#" "SEGMENT_TYPE_ID",NULL "SEGMENT_SUBTYPE", "A187"."TS#" "TABLESPACE_ID", "A187"."NAME" "TABLESPACE_NAME", "A187"."BLOCKSIZE" "BLOCKSIZE", "A185"."FILE#" "HEADER_FILE", "A186"."BLOCK#" "HEADER_BLOCK", "A186"."BLOCKS"*"A187"."BLOCKSIZE" "BYTES", "A186"."BLOCKS" "BLOCKS", "A186"."EXTENTS" "EXTENTS", "A186"."INIEXTS"*"A187"."BLOCKSIZE" "INITIAL_EXTENT", "A186"."EXTSIZE"*"A187"."BLOCKSIZE" "NEXT_EXTENT", "A186"."MINEXTS" "MIN_EXTENTS", "A186"."MAXEXTS" "MAX_EXTENTS",DECODE(BITAND("A186"."SPARE1",4194304),4194304, "A186"."BITMAPRANGES",NULL) "MAX_SIZE",NULL "RETENTION",NULL "MINRETENTION",DECODE(BITAND("A187"."FLAGS",3),1,TO_NUMBER(NULL), "A186"."EXTPCT") "PCT_INCREASE",DECODE(BITAND("A187"."FLAGS",32),32,TO_NUMBER(NULL),DECODE("A186" ."LISTS",0,1, "A186"."LISTS")) "FREELISTS",DECODE(BITAND("A187"."FLAGS",32),32,TO_NUMBER(NULL),DECODE("A186"."G ROUPS",0,1, "A186"."GROUPS")) "FREELIST_GROUPS", "A186"."FILE#" "RELATIVE_FNO",BITAND("A186"."CACHEHINT",3) "BUFFER_POOL_ID",BITAND("A186"."CACHEHINT",12)/4 "FLASH_CACHE",BITAND("A186"."CACHEHINT",48)/16 "CELL_FLASH_CACHE",NVL("A186"."SPARE1",0) "SEGMENT_FLAGS", "A186"."HWMINCR" "SEGMENT_OBJD" FROM "SYS"."USER$" "A188", "SYS"."TS$" "A187", "SYS"."SEG$" "A186", "SYS"."FILE$" "A185" WHERE "A186"."TS#"="A187"."TS#" AND "A186"."USER#"="A188"."USER#"(+) AND "A186"."TYPE#"<>1 AND "A186"."TYPE#"<>5 AND
  119. 119. 124 "A186"."TYPE#"<>6 AND "A186"."TYPE#"<>8 AND "A186"."TYPE#"<>10 AND "A186"."TYPE#"<>11 AND "A186"."TS#"="A185"."TS#" AND "A186"."FILE#"="A185"."RELFILE#") UNION ALL (SELECT NVL("A184"."NAME",'SYS') "OWNER",'HEATMAP' "SEGMENT_NAME", NULL "PARTITION_NAME",'SYSTEM STATISTICS' "SEGMENT_TYPE", "A182"."TYPE#" "SEGMENT_TYPE_ID",NULL "SEGMENT_SUBTYPE", "A183"."TS#" "TABLESPACE_ID", "A183"."NAME" "TABLESPACE_NAME", "A183"."BLO CKSIZE" "BLOCKSIZE", "A181"."FILE#" "HEADER_FILE", "A182"."BLOCK#" "HEADER_BLOCK", "A182"."BLOCKS"*"A183"."BLOCKSIZE" "BYTES", "A182"."BLOCKS" "BLOCKS", "A182"."EXTENTS" "EXTENTS", "A182"."INIEXTS"*"A183"."BLOCKSIZE" "INITIAL_EXTENT", "A182"."EXTSIZE"*"A183"."BLOCKSIZE" "NEXT_EXTENT", "A182"."MINEXTS" "MIN_EXTENTS", "A182"."MAXEXTS" "MAX_EXTENTS",DECODE(BITAND("A182"."SPARE1",4194304),4194304, "A182"."BITMAPRANGES",NULL) "MAX_SIZE",NULL "RETENTION",NULL "MINRETENTION",DECODE(BITAND("A183"."FLAGS",3),1,TO_NUMBER(NULL), "A182"."EXTPCT") "PCT_INCREASE",DECODE(BITAND("A183"."FLAGS",32),32,TO_NUMBER(NULL),DEC ODE("A182"."LISTS",0,1, "A182"."LISTS")) "FREELISTS",DECODE(BITAND("A183"."FLAGS",32),32,TO_NUMBER(NULL),DECODE("A182"."G ROUPS",0,1, "A182"."GROUPS")) "FREELIST_GROUPS", "A182"."FILE#" "RELATIVE_FNO",BITAND("A182"."CACHEHINT",3) "BUFFER_POOL_ID", BITAND("A182"."CACHEHINT",12)/4 "FLASH_CACHE",BITAND("A18 2"."CACHEHINT",48)/16 "CELL_FLASH_CACHE",NVL("A182"."SPARE1",0) "SEGMENT_FLAGS", "A182"."HWMINCR" "SEGMENT_OBJD" FROM "SYS"."USER$" "A184",
  120. 120. 125 "SYS"."TS$" "A183", "SYS"."SEG$" "A182", "SYS"."FILE$" "A181" WHERE "A182"."TS#"="A183"."TS#" AND "A182"."USER#"="A184"."USER#"(+) AND "A182"."TYPE#"=11 AND "A182"."TS#"="A181"."TS#" AND "A182"."FILE#"="A181"."RELFILE#")) "A4") "A3", (SELECT "A5"."NAME" "OWNER", "A6"."NAME" "OBJECT_NAME", "A6"."SUBNAME" "SUBOBJECT_NAME", "A6"."OBJ#" "OBJECT_ID", "A6"."DATAOBJ#" "DATA_OBJECT_ID",DECODE("A6"."TYPE#",0,'NEXT OBJECT',1,'INDEX', 2,'TABLE',3,'CLUSTER',4,'VIEW',5,'SYNONYM ',6,'SEQUENCE',7,'PROCEDURE',8,'FUNCTION',9,'PACKAGE',11,'PACKAGE BODY',12, 'TRIGGER',13,'TYPE',14,'TYPE BODY',19,'TABLE PARTITION',20,'INDEX PARTITION', 21,'LOB',22,'LIBRARY',23,'DIRECTORY',24,'QUEUE',28,'JAVA SOURCE',29,'JAVA CLASS',30, 'JAVA RESOURCE',32,'INDEXTYPE',33,'OPERATOR',34, 'TABLE SUBPARTITION',35,'INDEX SUBPARTITION',40,'LOB PARTITION',41,'LOB SUBPARTITION',42 ,NVL( (SELECT 'REWRITE EQUIVALENCE' "'REWRITEEQUIVALENCE'" FROM SYS."SUM$" "A52" WHERE "A52"."OBJ#"="A6"."OBJ#" AND BITAND("A52"."XPFLAGS",8388608)=8388608),'MATERIALIZED VIEW'),43,'DIMENSION', 44,'CONTEXT',46,'RULE SET',47,'RESOURCE PLAN',48,'CONSUMER GROUP',55,'XML SCHEMA',56,'JAVA DATA',57,'EDITION',59,'RULE', 60,'CAPTURE',61,'APPLY',62,'EVALUATION CONTEXT',66,'JOB',67,'PROGRAM',68,'JOB CLASS',69, 'WINDOW',72,'SCHEDULER GROUP',74,'SCHEDULE',79,'CHAIN',81,'FILE GROUP',82,'MINING MODEL',87,'ASSEMBLY',90,'CREDENTIAL',92,'CUBE DIMENSION',93,'CUBE',94,'MEASURE FOLDER',95,'CUBE BUILD PROCESS',100,'FILE WATCHER', 101,'DESTINATION',114,'SQL TRANSLATION PROFILE',115,'UNIFIED AUDIT POLICY','UNDEFINED') "OBJECT_TYPE", "A6"."CTIME" "CREATED", "A6"."MTIME" "LAST_DDL_TIME",TO_CHAR("A6"."STIME",'YYYY-MM-DD:HH24:MI:SS') "TIMESTAMP",DEC ODE("A6"."STATUS",0,'N/A',1,'VALID','INVALID') "STATUS",DECODE(BITAND("A6"."FLAGS",2),0,'N',2,'Y','N') "TEMPORARY",DECODE(BITAND("A6"."FLAGS",4),0,'N',4,'Y','N') "GENERATED",DECODE(BITAND("A6"."FLAGS",16),0,'N',16,'Y','N') "SECONDARY", "A6"."NAMESPACE" "NAMESPACE", "A6"."DEFINING_EDITION" "EDITION_NAM E",DECODE(BITAND("A6"."FLAGS",196608),65536,'METADATA LINK',131072,'OBJECT LINK','NONE') "SHARING", CASE WHEN ("A6"."TYPE#"=4 OR "A6"."TYPE#"=5 OR
  121. 121. 16 ... 126 more pages
  122. 122. back to temporal validity 127
  123. 123. SQL> variable c clob SQL> begin 2 dbms_utility.expand_sql_text( 3 q'{select * from emp_temporal 4 as of period for valid_range '01-FEB-14'}',:c); 6 end; 7 /
  124. 124. SQL> print c C ------------------------------------------------ SELECT "A1"."EMPNO" ... FROM ( SELECT "A2"."EMPNO" "EMPNO", "A2"."NAME" FROM "SCOTT"."EMP_TEMPORAL" "A2" WHERE ("A2"."START_DT" IS NULL OR "A2"."START_DT"<='01-FEB-14') AND ("A2"."END_DT" IS NULL OR "A2"."END_DT">'01-FEB-14') ) "A1"
  125. 125. existing tables
  126. 126. SQL> desc EMPLOYEE Name Null? Type ------------------------- -------- --------------- EMPNO NUMBER(4) ENAME VARCHAR2(10) JOB VARCHAR2(9) MGR NUMBER(4) HIREDATE DATE SAL NUMBER(7,2) COMM NUMBER(12,2) DEPTNO NUMBER(2) SQL> alter table EMPLOYEE add period for TIME_RANGE; Table altered.
  127. 127. SQL> desc EMPLOYEE Name Null? Type ------------------------- -------- --------------- EMPNO NUMBER(4) ENAME VARCHAR2(10) JOB VARCHAR2(9) MGR NUMBER(4) HIREDATE DATE SAL NUMBER(7,2) COMM NUMBER(12,2) DEPTNO NUMBER(2) still looks the same ?
  128. 128. SQL> select column_name , hidden_column 2 from user_tab_cols 3 where table_name = 'EMPLOYEE' 4 order by column_id; COLUMN_NAME HIDDEN_COLUMN ------------------------------ ------------- EMPNO NO ENAME NO JOB NO MGR NO HIREDATE NO SAL NO COMM NO DEPTNO NO TIME_RANGE_START YES TIME_RANGE_END YES TIME_RANGE YES
  129. 129. multi temporal validity
  130. 130. SQL> alter table EMP_TEMPORAL add period for CAL_RANGE; Table altered. SQL> alter table EMP_TEMPORAL add period for FINYR_RANGE; Table altered.
  131. 131. maybe a 12.x feature ?
  132. 132. no temporal constraints
  133. 133. SQL> alter table EMP_TEMPORAL add primary key (empno); Table altered. SQL> insert into EMP_TEMPORAL 2 (empno, name, start_dt, end_dt ) 3 values (20,'BROWN', '01-FEB-14','01-MAR-14'); 1 row created. SQL> insert into EMP_TEMPORAL 2 (empno, name, start_dt, end_dt ) 3 values (20,'BROWN', '01-MAY-14','01-SEP-14'); insert into EMP_TEMPORAL * ERROR at line 1: ORA-00001: unique constraint (SCOTT.SYS_C009892) violated
  134. 134. add START_DT to primary key ?
  135. 135. no temporal validation
  136. 136. SQL> insert into EMP_TEMPORAL 2 (empno, name, start_dt, end_dt ) 3 values (10,'JONES', '01-JAN-14','01-MAY-14'); 1 row created. SQL> insert into EMP_TEMPORAL 2 (empno, name, start_dt, end_dt ) 3 values (10,'JONES', '01-FEB-14','01-MAR-14'); 1 row created.
  137. 137. no temporal DML
  138. 138. SQL> update EMP_TEMPORAL 2 as of period for valid_range '01-FEB-14' 3 set sal = 10 4 where empno = 20; as of period for valid_range '01-FEB-14' * ERROR at line 2: ORA-08187: snapshot expression not allowed here
  139. 139. SQL> update ( 2 select * from EMP_TEMPORAL 3 as of period for valid_range '01-FEB-14' 4 where empno = 7369 5 ) 6 set sal = 10; 1 rows updated.
  140. 140. "Temporal validity is not supported with a multitenant container database" (12.1.0.1)
  141. 141. Feature invisible columns
  142. 142. have been there "forever"
  143. 143. function based indexes
  144. 144. set column unused
  145. 145. SQL> create table T 2 ( x int, 3 y int); Table created. SQL> create index IX on T (x+0); Index created. SQL> alter table T set unused column Y; Table altered.
  146. 146. SQL> select column_name, data_default 2 from USER_TAB_COLS 3 where table_name = 'T' 4 order by column_id; COLUMN_NAME DATA_DEFAULT ------------------------------ ---------------- X SYS_NC00003$ "X"+0 SYS_C00002_14020720:50:28$
  147. 147. now exposed to us
  148. 148. SQL> create table T ( c1 int, c2 int, c3 int ); SQL> desc T Name Null? Type ---------------------------- -------- ------- C1 NUMBER(38) C2 NUMBER(38) C3 NUMBER(38) SQL> alter table T modify c1 invisible; SQL> desc T Name Null? Type ---------------------------- -------- ------- C2 NUMBER(38) C3 NUMBER(38)
  149. 149. and an idiosyncracy...
  150. 150. SQL> alter table T modify c1 visible; SQL> desc T Name Null? Type ---------------------------- -------- ------- C2 NUMBER(38) C3 NUMBER(38) C1 NUMBER(38)
  151. 151. requires code discipline
  152. 152. SQL> desc T Name Null? Type ---------------------- -------- -------------------- C1 NUMBER(38) C2 NUMBER(38) C3 NUMBER(38) SQL> create or replace 2 procedure P is 3 begin 4 insert into T values (1,10,100); 6 end; SQL> exec P SQL> select * from T; C1 C2 C3 ---------- ---------- ---------- 1 10 100
  153. 153. SQL> alter table T modify c1 invisible; Table altered. SQL> alter table T modify c1 visible; Table altered. SQL> desc T Name Null? Type ------------------- -------- -------------------- C2 NUMBER(38) C3 NUMBER(38) C1 NUMBER(38)
  154. 154. SQL> exec P PL/SQL procedure successfully completed. SQL> select c1,c2,c3 from t; C1 C2 C3 ---------- ---------- ---------- 1 10 100 100 1 10
  155. 155. SQL> create or replace 2 procedure FIX_COLS(p_tab varchar2, p_col_list varchar2) is 3 l_col_list varchar2(1000) := p_col_list||','; 4 type clist is table of varchar2(30) 5 index by pls_integer; 6 c clist; 7 8 l_col varchar2(30); 9 l_id int; 10 begin 11 while instr(l_col_list,',') > 1 loop 12 c(c.count+1) := substr(l_col_list,1,instr(l_col_list,',')-1); 13 l_col_list := substr(l_col_list,instr(l_col_list,',')+1); 14 dbms_output.put_line(c(c.count)); 15 end loop; 16 17 for i in 1 .. c.count loop 18 loop 19 select column_name 20 into l_col 21 from user_tab_columns 22 where table_name = p_tab 23 and column_id = i; 24 25 exit when l_col = c(i); 26 27 execute immediate 'alter table '||p_tab||' modify '||l_col||' invisible'; 28 execute immediate 'alter table '||p_tab||' modify '||l_col||' visible'; 29 end loop; 30 end loop; 31 end; 32 /
  156. 156. SQL> exec FIX_COLS('T','C1,C2,C3'); PL/SQL procedure successfully completed. SQL> desc T Name Null? Type ---------------------------- -------- ------- C1 NUMBER(38) C2 NUMBER(38) C3 NUMBER(38)
  157. 157. so what's the appeal ?
  158. 158. rollout new code online
  159. 159. SQL> create table T ( c1 int, c2 int ) ; Table created. SQL> create or replace 2 procedure BAD_APP is 3 begin 4 insert into T 5 select object_id, data_object_id 6 from all_objects 7 where rownum < 10; 8 end; 9 / Procedure created. SQL> exec BAD_APP; PL/SQL procedure successfully completed.
  160. 160. new application
  161. 161. SQL> alter table T add c3 int; Table altered. SQL> create or replace 2 procedure NEW_APP is 3 begin 4 for i in ( select c1,c2,c3 from T ) 5 loop 6 dbms_output.put_line(i.c1); 7 dbms_output.put_line(i.c2); 8 dbms_output.put_line(i.c3); 9 end loop; 10 end; 11 / Procedure created.
  162. 162. SQL> exec NEW_APP; 28 28 15 15 29 29 25 25 54 PL/SQL procedure successfully completed.
  163. 163. SQL> exec BAD_APP BEGIN BAD_APP; END; * ERROR at line 1: ORA-06550: line 1, column 7: PLS-00905: object SCOTT.BAD_APP is invalid ORA-06550: line 1, column 7: PL/SQL: Statement ignored
  164. 164. SQL> alter table T modify c3 invisible; Table altered. SQL> exec NEW_APP; 28 28 15 15 29 29 25 25 54 PL/SQL procedure successfully completed. SQL> exec BAD_APP; PL/SQL procedure successfully completed.
  165. 165. tools
  166. 166. SQL> create table T ( c1 int, c2 int invisible); Table created. SQL> desc T Name Null? Type ------------------------- -------- ------------------ C1 NUMBER(38) SQL> set colinvisible ON SQL> desc T Name Null? Type ------------------------- -------- ----------- C1 NUMBER(38) C2 (INVISIBLE) NUMBER(38)
  167. 167. SQL> alter table T add "C3 (INVISIBLE)" int; Table altered. SQL> desc T Name Null? Type ------------------------- -------- ------------ C1 NUMBER(38) C3 (INVISIBLE) NUMBER(38) C2 (INVISIBLE) NUMBER(38)
  168. 168. 176 Feature: better truncate
  169. 169. 177 SQL> create table PARENT ( p int primary key ); Table created. SQL> create table CHILD 2 ( c int primary key, 3 p int references PARENT ( p ) 4 ); Table created. SQL> insert into PARENT values (1); 1 row created. SQL> insert into CHILD values (1,1); 1 row created.
  170. 170. 178 SQL> truncate table PARENT; truncate table PARENT * ERROR at line 1: ORA-02266: unique/primary keys in table referenced by enabled foreign keys
  171. 171. 179 12c
  172. 172. 180 SQL> truncate table PARENT cascade; Table truncated.
  173. 173. 181 SQL> alter table child modify 2 constraint CHILD_FK on delete cascade; ERROR at line 1: ORA-00933: SQL command not properly ended SQL> alter table child add 2 constraint NEW_FK foreign key ( p ) 3 references parent ( p ) on delete cascade; ERROR at line 1: ORA-02275: such a referential constraint already exists in the table
  174. 174. 182 full cascade
  175. 175. 183 referential partitions
  176. 176. 184 Feature session level sequence
  177. 177. 185 SQL> create sequence SESS_SEQ session; Sequence created.
  178. 178. 186 SQL> select sess_seq.nextval from dual; NEXTVAL ---------- 1 SQL> conn scott/tiger Connected. SQL> select sess_seq.nextval from dual; NEXTVAL ---------- 1
  179. 179. 187 contention
  180. 180. 188 SQL> create sequence NORMAL cache 1000; Sequence created. SQL> alter session set sql_trace = true; Session altered.
  181. 181. 189 SQL> insert into GTT 2 select SESS_SEQ.NEXTVAL 3 from dual 4 connect by level < 50000; 49999 rows created. SQL> insert into GTT 2 select NORMAL.NEXTVAL 3 from dual 4 connect by level < 50000; 49999 rows created.
  182. 182. 190 insert into GTT select SESS_SEQ.NEXTVAL from dual connect by level < 50000 call count cpu elapsed disk query ------- ------ -------- ---------- ---------- ---------- Parse 1 0.00 0.00 0 0 Execute 1 0.25 0.25 0 145 Fetch 0 0.00 0.00 0 0 ------- ------ -------- ---------- ---------- ---------- total 2 0.25 0.25 0 145
  183. 183. 191 insert into GTT select NORMAL.NEXTVAL from dual connect by level < 50000 call count cpu elapsed disk query ------- ------ -------- ---------- ---------- ---------- Parse 1 0.00 0.00 0 0 Execute 1 0.35 0.35 0 147 Fetch 0 0.00 0.00 0 0 ------- ------ -------- ---------- ---------- ---------- total 2 0.35 0.35 0 147
  184. 184. 192 update SEQ$ set increment$=:2,minvalue=:3,maxvalue=:4, cycle#=:5,order$=:6, cache=:7,highwater=:8,audit$=:9, flags=:10,partcount=:11 where obj#=:1 call count cpu elapsed disk query ------- ------ -------- ---------- ---------- ---------- Parse 1 0.00 0.00 0 0 Execute 50 0.00 0.00 0 50 Fetch 0 0.00 0.00 0 0 ------- ------ -------- ---------- ---------- ---------- total 51 0.00 0.00 0 50
  185. 185. 193 but ...
  186. 186. Lyrics "Players gonna play, play, play, play, play Haters gonna hate, hate, hate, hate, hate Gonna shake, shake, shake, shake, shake Shake it off, Shake it off Fakers gonna fake, fake, fake, fake, fake Shake it off, I shake it off, I, I, I shake it off, I shake it off, I, I, I shake it off, I shake it off, I, I, I shake it off, I shake it off Hey, hey, hey Yeah ohhh Shake it off, I shake it off, I, I, I shake it off, I shake it off, I, I, I shake it off, I shake it off I, I, I shake it off, I shake it off"
  187. 187. 196 substance
  188. 188. 197 why ?
  189. 189. 198 SQL> select X 2 from GTT; X ---------- 1 2 3 4 5 6 7 8 9 ... SQL> select X 2 from GTT; X ---------- 1 2 3 4 5 6 7 8 9 ...
  190. 190. 199
  191. 191. 200 please let me know ....
  192. 192. 201 perhaps more potential ...
  193. 193. 202 SQL> alter sequence SEQ 2 maxvalue 1000000 partition 8; Sequence altered. SQL> select seq.nextval x from dual; X -------------------------- 2000005 ... 1000000 2000000 3000000 not yet documented ...
  194. 194. 203 Feature defaults
  195. 195. 204 the most common ...
  196. 196. 205 and the absolute worst ...
  197. 197. 206 usage of triggers
  198. 198. 207 SQL> create sequence seq; Sequence created. SQL> create table T ( pk number , c1 int); Table created. SQL> create or replace 2 trigger FILL_IN_PK 3 before insert on T 4 for each row 5 begin 6 select seq.nextval into :new.pk from dual; 7 end; 8 / Trigger created.
  199. 199. 208 SQL> insert into T values (10,20); 1 row created. SQL> select * from T; PK C1 ---------- ---------- 1 20
  200. 200. 209 we got smarter
  201. 201. 210 SQL> create or replace 2 trigger FILL_IN_PK 3 before insert on T 4 for each row 5 when ( new.pk is null ) 6 begin 7 select seq.nextval into :new.pk from dual; 8 end; 9 / SQL> insert into T values (20,20); SQL> select * from T; PK C1 ---------- ---------- 1 20 20 20
  202. 202. triggers
  203. 203. over rated ... for that stuff
  204. 204. insert /* with trigger */ into T select rownum, rownum from dual connect by level <= 50000 call count cpu elapsed disk query current ------- ------ -------- ---------- ---------- ---------- ---------- Parse 1 0.00 0.00 0 0 0 Execute 1 5.64 5.64 0 466 1608 Fetch 0 0.00 0.00 0 0 0 ------- ------ -------- ---------- ---------- ---------- ---------- total 2 5.64 5.65 0 466 1608
  205. 205. insert /* without trigger */ into T select rownum, rownum from dual connect by level <= 50000 call count cpu elapsed disk query current ------- ------ -------- ---------- ---------- ---------- ---------- Parse 1 0.00 0.00 0 0 0 Execute 1 0.09 0.15 0 466 1620 Fetch 0 0.00 0.00 0 0 0 ------- ------ -------- ---------- ---------- ---------- ---------- total 2 0.09 0.15 0 466 1620
  206. 206. 12c ... finally !
  207. 207. 216 SQL> create table T ( 2 pk number default seq.nextval, 3 c1 int); Table created. Oracle 7, June 1992
  208. 208. 217 SQL> insert into T ( c1 ) values ( 0); SQL> select * from T; PK C1 ---------- ---------- 2 0 SQL> insert into T ( pk, c1 ) values (default, 1) ; SQL> select * from T; PK C1 ---------- ---------- 2 0 3 1
  209. 209. insert /* with default */ into T select rownum, rownum from dual connect by level <= 50000 call count cpu elapsed disk query current ------- ------ -------- ---------- ---------- ---------- ---------- Parse 1 0.00 0.00 0 0 0 Execute 1 0.06 0.07 0 467 1608 Fetch 0 0.00 0.00 0 0 0 ------- ------ -------- ---------- ---------- ---------- ---------- total 2 0.06 0.08 0 467 1608
  210. 210. other default improvements
  211. 211. "identity"
  212. 212. 221 SQL> drop table t purge; Table dropped. SQL> create table T 2 ( pk number generated as identity , 3 c1 int); Table created. SQL> select object_id, object_name, 2 object_type from user_objects; OBJECT_ID OBJECT_NAME OBJECT_TYPE ---------- ------------------ ------------ 414914 T TABLE 414915 ISEQ$$_414914 SEQUENCE
  213. 213. 222 SQL> @pr "select * from user_sequences" SEQUENCE_NAME : ISEQ$$_414914 MIN_VALUE : 1 MAX_VALUE : 9999999999999999999999 INCREMENT_BY : 1 CYCLE_FLAG : N ORDER_FLAG : N CACHE_SIZE : 20 LAST_NUMBER : 1 PARTITION_COUNT : SESSION_FLAG : N KEEP_VALUE : N
  214. 214. 223 SQL> create table T 2 ( pk number 3 generated as identity (cache 1000) 4 , c1 int); Table created. SQL> insert into T values (1,2); insert into T values (1,2) * ERROR at line 1: ORA-32795: cannot insert into a generated always identity column
  215. 215. more null control
  216. 216. before 12c
  217. 217. 226 SQL> create table T ( 2 pk int, 3 status varchar2(1) default 'N' ); Table created. SQL> insert into T (pk) values (1); 1 row created. SQL> insert into T (pk, status) values (2,default); 1 row created. SQL> insert into T (pk, status) values (3,null); 1 row created.
  218. 218. 227 SQL> select * from T; PK STATUS ---------- ------ 1 N 2 N 3
  219. 219. workarounds ugly
  220. 220. 229 SQL> create or replace 2 procedure ins(p_pk int, p_status varchar2) is 3 begin 4 if p_status is null then 5 insert into T (pk, status) 6 values (p_pk, default ); 7 else 8 insert into T (pk, status) 9 values (p_pk, p_status ); 10 end if; 11 end; 12 / Procedure created.
  221. 221. 12c "on null"
  222. 222. 231 SQL> create table T ( 2 pk int, 3 status varchar2(1) default on null 'N' , 4 start_date date default on null 5 trunc(sysdate,'MM'), 6 commission int default on null 1000, 7 job_level int default on null 1 8 ); Table created. SQL> insert into T values (1,null,null,null,null); 1 row created. SQL> select * from T; PK S START_DAT COMMISSION JOB_LEVEL ---------- - --------- ---------- ---------- 1 N 01-JAN-14 1000 1
  223. 223. Feature PL/SQL debugging
  224. 224. it all starts off easy
  225. 225. SQL> create or replace procedure P is 2 x int; 3 y int; 4 begin 5 6 x := 10; 7 8 select count(*) 9 into y 10 from all_objects 11 where object_name = 'NUFFIN'; 12 13 x := x / y; 14 15 select rownum 16 into x 17 from dual; 18 19 end; 20 / Procedure created.
  226. 226. SQL> exec P; BEGIN P; END; * ERROR at line 1: ORA-01476: divisor is equal to zero ORA-06512: at "SCOTT.P", line 13 ORA-06512: at line 1
  227. 227. SQL> create or replace procedure P is 2 x int; 3 y int; 4 begin 5 6 x := 10; 7 8 select count(*) 9 into y 10 from all_objects 11 where object_name = 'NUFFIN'; 12 13 x := x / y; 14 15 select rownum 16 into x 17 from dual; 18 19 end; 20 / Procedure created.
  228. 228. ... and downhill from there
  229. 229. SQL> create or replace procedure P is 2 x int; 3 y int; 4 begin 5 6 x := 10; 7 8 select count(*) 9 into y 10 from all_objects 11 where object_name = 'NUFFIN'; 12 13 x := x / y; 14 15 select rownum 16 into x 17 from dual; 18 19 exception 20 when others then 21 log_error; 22 raise; 23 end; 24 /
  230. 230. SQL> exec P; BEGIN P; END; * ERROR at line 1: ORA-01476: divisor is equal to zero ORA-06512: at "SCOTT.P", line 22
  231. 231. SQL> create or replace procedure P is 2 x int; 3 y int; 4 begin 5 6 x := 10; 7 8 select count(*) 9 into y 10 from all_objects 11 where object_name = 'NUFFIN'; 12 13 x := x / y; 14 15 select rownum 16 into x 17 from dual; 18 19 exception 20 when others then 21 log_error; 22 raise; 23 end; 24 / ?
  232. 232. SQL> create or replace procedure P is 2 x int; 3 y int; 4 begin 5 6 x := 10; 7 8 select count(*) 9 into y 10 from all_objects 11 where object_name = 'NUFFIN'; 12 13 x := x / y; 14 15 select rownum 16 into x 17 from dual; 18 19 exception 20 when others then 21 dbms_output.put_line( 22 dbms_utility.format_call_stack); 23 raise; 24 end; 25 /
  233. 233. SQL> exec P; ----- PL/SQL Call Stack ----- object line object handle number name 0x14b1e3900 21 procedure SCOTT.P 0x12521b8d8 1 anonymous block BEGIN P; END; * ERROR at line 1: ORA-01476: divisor is equal to zero ORA-06512: at "SCOTT.P", line 23 ORA-06512: at line 1
  234. 234. SQL> create or replace procedure P is 2 x int; 3 y int; 4 l_debug varchar2(4000); 5 begin 6 l_debug := dbms_utility.format_call_stack; 7 8 x := 10; 9 10 l_debug := dbms_utility.format_call_stack; 11 select count(*) 12 into y 13 from all_objects 14 where object_name = 'NUFFIN'; 15 16 l_debug := dbms_utility.format_call_stack; 17 x := x / y; 18 19 l_debug := dbms_utility.format_call_stack; 20 select rownum 21 into x 22 from dual; 23 24 exception 25 when others then 26 dbms_output.put_line(l_debug); 27 raise; 28 end;
  235. 235. SQL> exec P; ----- PL/SQL Call Stack ----- object line object handle number name 0x14b1e3900 16 procedure SCOTT.P 0x12521b8d8 1 anonymous block BEGIN P; END; * ERROR at line 1: ORA-01476: divisor is equal to zero ORA-06512: at "SCOTT.P", line 27 ORA-06512: at line 1
  236. 236. SQL> create or replace procedure P is 2 x int; 3 y int; 4 l_debug varchar2(4000); 5 begin 6 l_debug := dbms_utility.format_call_stack; 7 ... 24 exception 25 when others then 26 l_debug := substr(l_debug,instr(l_debug,chr(10),1,3)); 27 l_debug := regexp_replace(l_debug,chr(10)||'.*$'); 28 dbms_output.put_line(l_debug); 29 raise; 30 end; 31 /
  237. 237. SQL> exec P; 0x14b1e3900 16 procedure SCOTT.P BEGIN P; END; * ERROR at line 1: ORA-01476: divisor is equal to zero ORA-06512: at "SCOTT.P", line 29 ORA-06512: at line 1
  238. 238. 10g got better
  239. 239. DBMS_UTILITY.FORMAT_ERROR_BACKTRACE
  240. 240. SQL> create or replace procedure P is 2 x int; 3 y int; 4 l_debug varchar2(4000); 5 begin 6 l_debug := dbms_utility.format_call_stack; 7 8 x := 10; 9 ... 23 24 exception 25 when others then 26 dbms_output.put_line( 27 DBMS_UTILITY.FORMAT_ERROR_BACKTRACE ); 28 raise; 29 end;
  241. 241. SQL> exec P; ORA-06512: at "SCOTT.P", line 17 BEGIN P; END; * ERROR at line 1: ORA-01476: divisor is equal to zero ORA-06512: at "SCOTT.P", line 27 ORA-06512: at line 1
  242. 242. 12c .... finally
  243. 243. UTL_CALL_STACK
  244. 244. SQL> create or replace procedure P is 2 x int; 3 y int; 4 begin 5 x := 10; 6 ... 17 18 exception 19 when others then 20 for i in 1 .. utl_call_stack.dynamic_depth loop 21 dbms_output.put_line( 22 utl_call_stack.unit_line(i)||'-'|| 23 utl_call_stack.concatenate_subprogram( 24 utl_call_stack.subprogram(i)) 25 ); 26 end loop; 27 raise; 28 end;
  245. 245. SQL> exec P; 21-P 1-__anonymous_block BEGIN P; END; * ERROR at line 1: ORA-01476: divisor is equal to zero ORA-06512: at "SCOTT.P", line 27 ORA-06512: at line 1
  246. 246. value in "real world"
  247. 247. SQL> create or replace package PKG is 2 procedure p; 3 procedure p1; 4 procedure p2; 5 procedure p3; 6 end; 7 / Package created.
  248. 248. SQL> create or replace package body PKG is 2 3 procedure p is ... 19 20 exception 21 when others then 22 for i in 1 .. utl_call_stack.dynamic_depth loop 23 dbms_output.put_line( 24 utl_call_stack.unit_line(i)||'-'|| 25 utl_call_stack.concatenate_subprogram( 26 utl_call_stack.subprogram(i)) 27 ); 28 end loop; 29 raise; 30 end; 31 32 procedure p1 is begin p; end; 33 procedure p2 is begin p1; end; 34 procedure p3 is begin p2; end; 35 36 end; 37 /
  249. 249. SQL> exec pkg.p3 23-PKG.P 32-PKG.P1 33-PKG.P2 34-PKG.P3 1-__anonymous_block BEGIN pkg.p3; END; * ERROR at line 1: ORA-01476: divisor is equal to zero ORA-06512: at "SCOTT.PKG", line 29 ORA-06512: at "SCOTT.PKG", line 32 ORA-06512: at "SCOTT.PKG", line 33 ORA-06512: at "SCOTT.PKG", line 34 ORA-06512: at line 1
  250. 250. did you miss it ?
  251. 251. SQL> exec pkg.p3 23-PKG.P 32-PKG.P1 33-PKG.P2 34-PKG.P3 1-__anonymous_block BEGIN pkg.p3; END; subprogram !!! * ERROR at line 1: ORA-01476: divisor is equal to zero ORA-06512: at "SCOTT.PKG", line 29 ORA-06512: at "SCOTT.PKG", line 32 ORA-06512: at "SCOTT.PKG", line 33 ORA-06512: at "SCOTT.PKG", line 34 ORA-06512: at line 1
  252. 252. Feature inline PLSQL in SQL
  253. 253. every system ...
  254. 254. ... I've worked on
  255. 255. struggles with case
  256. 256. no correlation :-)
  257. 257. SQL> select vendor 2 from service_provider; VENDOR ------------------------------ jones brown SMITH sigh...
  258. 258. "no problem.... I'll use initcap"
  259. 259. SQL> select initcap(vendor) 2 from service_provider; INITCAP(VENDOR) ------------------------------ Jones Brown Smith
  260. 260. until ...
  261. 261. SQL> select initcap(vendor) 2 from service_provider; INITCAP(VENDOR) ------------------------------ Jones Brown Smith Mcdonald Johnson'S uh oh
  262. 262. home grown
  263. 263. SQL> create or replace 2 function my_initcap(p_string varchar2) return varchar2 is 3 l_string varchar2(1000) := p_string; 4 begin 5 if regexp_like(l_string,'(Mac[A-Z]|Mc[A-Z])') then 6 null; 7 elsif l_string like '''%' then 8 null; 9 else 10 l_string := initcap(l_string); 11 if l_string like '_''S%' then 12 null; 13 else 14 l_string := replace(l_string,'''S','''s'); 15 end if; 16 end if; 17 18 return l_string; 19 end; 20 / Function created.
  264. 264. cool ...
  265. 265. SQL> select my_initcap(vendor) 2 from service_provider; MY_INITCAP(VENDOR) -------------------------- Jones Brown Smith McDonald Johnson's
  266. 266. until ...
  267. 267. "you stupid developer... don't call PLSQL from SQL !!!!"
  268. 268. SQL> select max(x) 2 from ( 3 select /*+ no_merge */ initcap(source) x 4 from large_table 5 ); ... SQL> select max(x) 2 from ( 3 select /*+ no_merge */ my_initcap(source) x 4 from large_table 5 ); Elapsed: 00:00:00.48 Elapsed: 00:00:09.37
  269. 269. it can be done in SQL
  270. 270. SQL> select 2 case 3 when regexp_like(vendor,'(Mac[A-Z]|Mc[A-Z])') then vendor 4 when vendor like '''%' then vendor 5 when initcap(vendor) like '_''S%' then vendor 6 else replace(initcap(vendor),'''S','''s') 7 end ugh 8 from service_provider; UGH ------------------------------- Jones Brown Smith McDonald Johnson's
  271. 271. "Always code as if the person who ends up maintaining your code is a psychopathic killer who knows where you live." - source unknown
  272. 272. 12c ... user defined functions
  273. 273. SQL> WITH 2 function my_initcap(p_string varchar2) 3 return varchar2 is 4 l_string varchar2(1000) := p_string; 5 begin 6 if regexp_like(l_string,'(Mac[A-Z]|Mc[A-Z])') then 7 null; 8 elsif l_string like '''%' then ... 17 18 return l_string; 19 end; 20 select my_initcap(vendor) 21 from service_provider; MY_INITCAP(VENDOR) ----------------------------------------- Jones Brown Smith McDonald O'Brien Johnson's
  274. 274. multiple routines
  275. 275. SQL> WITH 2 function is_scottish(p_string varchar2) return boolean is 3 begin 4 return regexp_like(p_string,'(Mac[A-Z]|Mc[A-Z])'); 5 end; 6 function my_initcap(p_string varchar2) return varchar2 is 7 l_string varchar2(1000) := p_string; 8 begin 9 if is_scottish(l_string) then 10 null; 11 elsif l_string like '''%' then 12 null; 13 else 14 l_string := initcap(l_string); 15 if l_string like '_''S%' then 16 null; 17 else 18 l_string := replace(l_string,'''S','''s'); 19 end if; 20 end if; 21 22 return l_string; 23 end; 24 select my_initcap(surname) 25 from names; 26 /
  276. 276. note: 12c client
  277. 277. 11.2 and below
  278. 278. SQL> WITH 2 function my_initcap(p_string varchar2) return varchar2 is 3 l_string varchar2(1000) := p_string; function my_initcap(p_string varchar2) return varchar2 is * ERROR at line 2: ORA-06553: PLS-103: Encountered the symbol "end-of-file" when expecting one of the following: . ( * @ % & = - + ; < / > at in is mod remainder not rem <an exponent (**)> <> or != or ~= >= <= <> and or like like2 like4 likec between || multiset member submultiset SQL> begin 2 if regexp_like(l_string,'(Mac[A-Z]|Mc[A-Z])') then 3 null; 4 elsif l_string like '''%' then 5 null; 6 else 7 l_string := initcap(l_string);
  279. 279. and a blast from the past :-)
  280. 280. SQL> create or replace 2 procedure NAMES_PROCESSOR is 3 cursor C is 4 WITH 5 function my_initcap(p_string varchar2) return varchar2 is 6 l_string varchar2(1000) := p_string; 7 begin ... 23 select my_initcap(vendor) from service_provider; 25 begin 26 null; 27 end; 28 / Warning: Procedure created with compilation errors. SQL> sho err Errors for PROCEDURE NAMES_PROCESSOR: LINE/COL ERROR -------- ------------------------------------------------ 3/7 PL/SQL: SQL Statement ignored 4/18 PL/SQL: ORA-00905: missing keyword 22/7 PLS-00103: Encountered the symbol "SELECT"
  281. 281. SQL> create or replace 2 procedure NAMES_PROCESSOR is 3 rc sys_refcursor; 4 begin 5 open rc for 6 q'{ WITH 7 function my_initcap(p_string varchar2) return varchar2 is 8 l_string varchar2(1000) := p_string; 9 begin ... 23 return l_string; 24 end; 25 select my_initcap(vendor) 26 from service_provider 27 }'; 28 end; 29 / Procedure created.
  282. 282. WITH_PLSQL unrelated to previous
  283. 283. DML (or complex SQL)
  284. 284. SQL> insert into CONTRACTS 2 WITH 3 function my_initcap(p_string varchar2) 4 return varchar2 is 5 l_string varchar2(1000) := p_string; 6 begin ... 20 end; 21 select my_initcap(vendor) 22 from service_provider; 23 / WITH * ERROR at line 2: ORA-32034: unsupported use of WITH clause
  285. 285. SQL> insert /*+ WITH_PLSQL */ into CONTRACTS 2 WITH 3 function my_initcap(p_string varchar2) 4 return varchar2 is 5 l_string varchar2(1000) := p_string; 6 begin ... 20 end; 21 select my_initcap(surname) 22 from names; 23 / 5 rows inserted.
  286. 286. determinism
  287. 287. SQL> with 2 function f return timestamp as 3 begin 4 return systimestamp; 5 end; 6 select f 7 from dual 8 connect by level <= 10; 9 / F ---------------------------------------- 05-JAN-14 08.09.43.969000000 PM 05-JAN-14 08.09.43.970000000 PM 05-JAN-14 08.09.43.970000000 PM 05-JAN-14 08.09.43.971000000 PM ...
  288. 288. DETERMINISTIC keyword
  289. 289. SQL> with 2 function f return timestamp DETERMINISTIC as 3 begin 4 return systimestamp; 5 end; 6 select f 7 from dual 8 connect by level <= 10; 9 / F ---------------------------------------- 05-JAN-14 08.09.52.145000000 PM 05-JAN-14 08.09.52.146000000 PM 05-JAN-14 08.09.52.146000000 PM 05-JAN-14 08.09.52.147000000 PM ...
  290. 290. conventional scalar caching
  291. 291. SQL> with 2 function f return timestamp as 3 begin 4 return systimestamp; 5 end; 6 select ( select f from dual ) 7 from dual 8 connect by level <= 10; 9 / F ---------------------------------------- 05-JAN-14 08.11.50.145000000 PM 05-JAN-14 08.11.50.145000000 PM 05-JAN-14 08.11.50.145000000 PM 05-JAN-14 08.11.50.145000000 PM ...
  292. 292. are they really faster ?
  293. 293. SQL> create or replace 2 function F return number is 3 begin 4 return 1; 5 end; 6 / Function created.
  294. 294. SQL> select sum(f) 2 from 3 ( select level from dual 4 connect by level <= 1000 ), 5 ( select level from dual 6 connect by level <= 1000 ) 7 ; SUM(F) ---------- 1000000 Elapsed: 00:00:02.04
  295. 295. SQL> with 2 function f1 return number is 3 begin 4 return 1; 5 end; 6 select sum(f1) 7 from 8 ( select level from dual 9 connect by level <= 1000 ), 10 ( select level from dual 11 connect by level <= 1000 ) 12 / SUM(F1) ---------- 1000000 Elapsed: 00:00:00.52
  296. 296. "but what about all my PLSQL !!!"
  297. 297. SQL> create or replace 2 function F return number is 3 pragma udf; 4 begin 5 return 1; 6 end; SQL> select sum(f) 2 from 3 ( select level from dual 4 connect by level <= 1000 ), 5 ( select level from dual 6 connect by level <= 1000 ); SUM(F) ---------- 1000000 Elapsed: 00:00:00.36
  298. 298. Feature top-n simplifications 308
  299. 299. "5 most recently hired employees" 309
  300. 300. SQL> select empno, ename, hiredate 2 from scott.emp 3 where rownum <= 5 4 order by hiredate desc; EMPNO ENAME HIREDATE ---------- ---------- ------------------- 7654 MARTIN 28/09/1981 00:00:00 7566 JONES 02/04/1981 00:00:00 7521 WARD 22/02/1981 00:00:00 7499 ALLEN 20/02/1981 00:00:00 7369 SMITH 17/12/1980 00:00:00 310
  301. 301. inline view 311
  302. 302. SQL> select * 2 from ( 3 select empno, ename, hiredate 4 from scott.emp 5 order by hiredate desc 6 ) 7 where rownum <= 2; EMPNO ENAME HIREDATE ---------- ---------- --------- 7876 ADAMS 23-MAY-87 7788 SCOTT 19-APR-87 312
  303. 303. ------------------------------------------------ | Id | Operation | Name | Rows | ------------------------------------------------ | 0 | SELECT STATEMENT | | 2 | |* 1 | COUNT STOPKEY | | | | 2 | VIEW | | 14 | |* 3 | SORT ORDER BY STOPKEY| | 14 | | 4 | TABLE ACCESS FULL | EMP | 14 | ------------------------------------------------ 313
  304. 304. SQL> select * 2 from ( 3 select 4 empno, ename, hiredate, 5 row_number() over ( order by hiredate desc) rn 6 from scott.emp 7 ) 8 where rn <= 2; 314
  305. 305. ------------------------------------------------- | Id | Operation | Name | Rows | ------------------------------------------------- | 0 | SELECT STATEMENT | | 14 | |* 1 | VIEW | | 14 | |* 2 | WINDOW SORT PUSHED RANK| | 14 | | 3 | TABLE ACCESS FULL | EMP | 14 | ------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("RN"<=2) 2 - filter(ROW_NUMBER() OVER ( ORDER BY HIREDATE") DESC )<=2) 315
  306. 306. 12c .... "easier" 316
  307. 307. SQL> select empno, ename, hiredate 2 from scott.emp 3 order by hiredate desc 4 fetch first 2 rows only; EMPNO ENAME HIREDATE ---------- ---------- --------- 7876 ADAMS 23-MAY-87 7788 SCOTT 19-APR-87 317
  308. 308. behind the scenes 318
  309. 309. ------------------------------------------------- | Id | Operation | Name | Rows | ------------------------------------------------- | 0 | SELECT STATEMENT | | 14 | |* 1 | VIEW | | 14 | |* 2 | WINDOW SORT PUSHED RANK| | 14 | | 3 | TABLE ACCESS FULL | EMP | 14 | ------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("from$_subquery$_002". "rowlimit_$$_rownumber"<=2) 2 - filter(ROW_NUMBER() OVER ( ORDER BY HIREDATE") DESC )<=2) 319
  310. 310. variations 320
  311. 311. SQL> select empno, ename, hiredate 2 from scott.emp 3 order by hiredate desc 4 fetch first 1 row only; EMPNO ENAME HIREDATE ---------- ---------- --------- 7876 ADAMS 23-MAY-87 321
  312. 312. SQL> select empno, ename, hiredate 2 from scott.emp 3 order by hiredate desc 4 fetch first 5 row only; EMPNO ENAME HIREDATE ---------- ---------- --------- 7876 ADAMS 23-MAY-87 7788 SCOTT 19-APR-87 7934 MILLER 23-JAN-82 7900 JAMES 03-DEC-81 7902 FORD 03-DEC-81 322
  313. 313. SQL> select empno, ename, hiredate 2 from scott.emp 3 order by hiredate desc 4 fetch first 10 percent rows only; EMPNO ENAME HIREDATE ---------- ---------- --------- 7876 ADAMS 23-MAY-87 7788 SCOTT 19-APR-87 323
  314. 314. pagination 324
  315. 315. SQL> select empno, ename, hiredate 2 from scott.emp 3 order by hiredate desc 4 offset 5 rows fetch next 3 rows only; EMPNO ENAME HIREDATE ---------- ---------- --------- 7839 KING 17-NOV-81 7654 MARTIN 28-SEP-81 7844 TURNER 08-SEP-81 325
  316. 316. idiosyncracies 326
  317. 317. SQL> select empno, ename, hiredate 2 from scott.emp 3 order by hiredate desc 4 fetch LAST 5 rows only; fetch LAST 5 rows only * ERROR at line 4: ORA-00905: missing keyword 327
  318. 318. SQL> select * 2 from ( 3 select empno, ename, hiredate 4 from scott.emp 5 order by hiredate asc 6 fetch first 5 rows only 7 ) 8 order by hiredate desc; EMPNO ENAME HIREDATE ---------- ---------- --------- 7698 BLAKE 01-MAY-81 7566 JONES 02-APR-81 7521 WARD 22-FEB-81 7499 ALLEN 20-FEB-81 7369 SMITH 17-DEC-80 328
  319. 319. no percent pagination 329
  320. 320. SQL> select empno, ename, hiredate 2 from scott.emp 3 order by hiredate desc 4 offset 20 percent fetch 5 next 10 percent rows only; offset 20 percent fetch next 10 percent rows only * ERROR at line 4: ORA-00905: missing keyword 330
  321. 321. plsql quirk 331
  322. 322. "Note that in real life, you would use bind variables instead of hard-coded literals" 332 - Tom Kyte, Oracle Magazine, Sep 13
  323. 323. SQL> declare 2 l_num number := 5; 3 begin 4 for i in ( 5 select empno, ename, hiredate 6 from scott.emp 7 order by hiredate desc 8 fetch first l_num rows only 9 ) 10 loop 11 null; 12 end loop; 13 end; 14 / declare * ERROR at line 1: ORA-03113: end-of-file on communication channel Process ID: 26618 Session ID: 25 Serial number: 53023 333
  324. 324. SQL> declare 2 l_num number := 5; 3 begin 4 for i in ( 5 select empno, ename, hiredate 6 from scott.emp 7 order by hiredate desc 8 fetch first cast(l_num as number) rows only 9 ) 10 loop 11 null; 12 end loop; 13 end; 14 / PL/SQL procedure successfully completed. 334 fixed in 12.1.0.2
  325. 325. Feature adaptive plans
  326. 326. SQL> create table PARENT ( p int, pdata varchar2(20) ); Table created. SQL> create table CHILD ( c int, p int, cdata char(200)); Table created. SQL> insert into PARENT 2 select rownum*2+1, rownum 3 from dual 4 connect by level <= 500; 500 rows created. SQL> insert into CHILD 2 select rownum, mod(rownum,1000)*2, rownum 3 from dual 4 connect by level < 10000; 9999 rows created.
  327. 327. SQL> exec dbms_stats.gather_table_stats('','PARENT') PL/SQL procedure successfully completed. SQL> exec dbms_stats.gather_table_stats('','CHILD') PL/SQL procedure successfully completed. SQL> create index CHILD_IX on CHILD ( p ) ; Index created. SQL> select count(*) from PARENT 2 where p < 10; COUNT(*) ---------- 4
  328. 328. SQL> set autotrace traceonly explain SQL> select * 2 from PARENT p, 3 CHILD c 4 where p.p < 10 5 and p.p = c.p; --------------------------------------------------------- | Id | Operation | Name | Rows | --------------------------------------------------------- | 0 | SELECT STATEMENT | | 4 | | 1 | NESTED LOOPS | | | | 2 | NESTED LOOPS | | 4 | |* 3 | TABLE ACCESS FULL | PARENT | 4 | |* 4 | INDEX RANGE SCAN | CHILD_IX | 1 | | 5 | TABLE ACCESS BY INDEX ROWID| CHILD | 1 | --------------------------------------------------------- Note ----- - this is an adaptive plan
  329. 329. now lets mess with it
  330. 330. SQL> insert into PARENT 2 select mod(rownum,5)*2+1, rownum 3 from dual 4 connect by level <= 20000; 20000 rows created. SQL> commit; Commit complete. SQL> select count(*) from PARENT 2 where p < 10; COUNT(*) ---------- 20004
  331. 331. a new cursor
  332. 332. SQL> select /*+ gather_plan_statistics */ * 2 from CHILD c, 3 PARENT p 4 where p.p < 10 5 and p.p = c.p; no rows selected SQL> select * 2 from table( 3 dbms_xplan.display_cursor( 4 null,null,'ALLSTATS LAST +ADAPTIVE'));
  333. 333. ----------------------------------------------------------- | Id | Operation | Name | ----------------------------------------------------------- | 0 | SELECT STATEMENT | | | * 1 | HASH JOIN | | |- 2 | NESTED LOOPS | | |- 3 | NESTED LOOPS | | |- 4 | STATISTICS COLLECTOR | | | * 5 | TABLE ACCESS FULL | PARENT | |- * 6 | INDEX RANGE SCAN | CHILD_IX | |- 7 | TABLE ACCESS BY INDEX ROWID | CHILD | | 8 | TABLE ACCESS BY INDEX ROWID BATCHED| CHILD | | * 9 | INDEX RANGE SCAN | CHILD_IX | -----------------------------------------------------------
  334. 334. ----------------------------------------------------------- | Id | Operation | Name | ----------------------------------------------------------- | 0 | SELECT STATEMENT | | | * 1 | HASH JOIN | | |- 2 | NESTED LOOPS | | |- 3 | NESTED LOOPS | | |- 4 | STATISTICS COLLECTOR | | | * 5 | TABLE ACCESS FULL | PARENT | |- * 6 | INDEX RANGE SCAN | CHILD_IX | |- 7 | TABLE ACCESS BY INDEX ROWID | CHILD | | 8 | TABLE ACCESS BY INDEX ROWID BATCHED| CHILD | | * 9 | INDEX RANGE SCAN | CHILD_IX | -----------------------------------------------------------
  335. 335. ----------------------------------------------------------- | Id | Operation | Name | ----------------------------------------------------------- | 0 | SELECT STATEMENT | | | * 1 | HASH JOIN | | |- 2 | NESTED LOOPS | | |- 3 | NESTED LOOPS | | |- 4 | STATISTICS COLLECTOR | | | * 5 | TABLE ACCESS FULL | PARENT | |- * 6 | INDEX RANGE SCAN | CHILD_IX | |- 7 | TABLE ACCESS BY INDEX ROWID | CHILD | | 8 | TABLE ACCESS BY INDEX ROWID BATCHED| CHILD | | * 9 | INDEX RANGE SCAN | CHILD_IX | -----------------------------------------------------------
  336. 336. ----------------------------------------------------------- | Id | Operation | Name | ----------------------------------------------------------- | 0 | SELECT STATEMENT | | | * 1 | HASH JOIN | | |- 2 | NESTED LOOPS | | |- 3 | NESTED LOOPS | | |- 4 | STATISTICS COLLECTOR | | | * 5 | TABLE ACCESS FULL | PARENT | |- * 6 | INDEX RANGE SCAN | CHILD_IX | |- 7 | TABLE ACCESS BY INDEX ROWID | CHILD | | 8 | TABLE ACCESS BY INDEX ROWID BATCHED| CHILD | | * 9 | INDEX RANGE SCAN | CHILD_IX | -----------------------------------------------------------
  337. 337. SQL> select * 2 from table( 3 dbms_xplan.display_cursor( 4 null,null,'ALLSTATS LAST')); --------------------------------------------------------- | Id | Operation | Name | --------------------------------------------------------- | 0 | SELECT STATEMENT | | |* 1 | HASH JOIN | | |* 2 | TABLE ACCESS FULL | PARENT | | 3 | TABLE ACCESS BY INDEX ROWID BATCHED| CHILD | |* 4 | INDEX RANGE SCAN | CHILD_IX | --------------------------------------------------------- Note ----- - this is an adaptive plan
  338. 338. just be aware
  339. 339. tools will (hopefully) catch up
  340. 340. Feature pattern matching 350
  341. 341. analytics ... since 8.1.6 351 median top n moving average etc
  342. 342. "analysis" often "patterns" 352
  343. 343. real example 353
  344. 344. 354
  345. 345. 355
  346. 346. AML 356 anti money laundering
  347. 347. "Find 10 consecutive deposits in a 24 hour period, then a withdrawal within three days of the last deposit, at a different branch" 357
  348. 348. ACCT TSTAMP WTHD_TSTAMP TYPE AMT ---------- ------------------ ------------------ ---- ------- 54261 25/01/13 17:20:55 D 100 54261 25/01/13 17:56:58 D 165 54261 26/01/13 11:24:14 D 30 54261 26/01/13 11:47:53 D 45 54261 26/01/13 12:59:38 D 100 54261 26/01/13 13:26:04 D 80 54261 26/01/13 14:41:09 D 50 54261 26/01/13 14:53:12 D 50 54261 26/01/13 15:15:05 D 50 54261 26/01/13 15:51:17 D 50 54261 26/01/13 16:15:02 D 120 54261 26/01/13 16:36:51 D 100 54261 26/01/13 16:55:09 D 100 54261 26/01/13 18:07:17 26/01/13 18:07:17 W -500 358
  349. 349. hard... with analytics 359
  350. 350. 12c 360
  351. 351. pattern matching 361
  352. 352. SQL> select acct, tstamp, wthd_tstamp, txn_type, amt 2 from account_txns 3 MATCH_RECOGNIZE 4 ( 5 partition by acct 6 order by tstamp 7 measures 8 dep.tstamp dep_tstamp, 9 wthd.tstamp wthd_tstamp 10 11 all rows per match 12 pattern ( dep{10,} wthd ) 13 define 14 dep as 15 txn_type = 'D', 16 wthd as 17 txn_type = 'W' 18 and last(dep.tstamp)-first(dep.tstamp) < interval '1' day 19 and wthd.tstamp - last(dep.tstamp) < interval '3' day 20 and wthd.loc_id != last(dep.loc_id) 21 ) 362
  353. 353. "What is the longest losing streak for customers since the start of the month" 363
  354. 354. SQL> select acct, started_losing, finished_losing 2 from account_txns 3 MATCH_RECOGNIZE 4 ( 5 partition by acct 6 order by tstamp 7 measures 8 tstamp as tstamp, outcome as outcome, 9 first(still_losing.tstamp) started_losing, 10 got_lucky.tstamp finished_losing 11 one row per match 12 pattern ( still_losing* got_lucky ) 13 define 14 still_losing as outcome = 'Lose' 15 and still_losing.outcome = 16 first(still_losing.outcome), 17 got_lucky as outcome = 'Win' 18 ); 364
  355. 355. ACCT STARTED_LOSING FINISHED_LOSING ---------- ------------------- ------------------- 66 01/02/2014 10:49:41 01/02/2014 16:30:01 66 01/02/2014 16:30:56 01/02/2014 17:23:06 66 01/02/2014 17:24:03 01/02/2014 18:11:32 66 01/02/2014 18:11:44 01/02/2014 19:13:04 66 01/02/2014 19:13:19 01/02/2014 19:44:04 66 01/02/2014 19:44:21 01/02/2014 20:15:33 184 02/02/2014 11:50:46 02/02/2014 12:23:49 184 02/02/2014 12:26:29 02/02/2014 12:56:57 184 02/02/2014 12:57:00 02/02/2014 13:19:51 184 02/02/2014 13:23:35 08/02/2014 14:24:35 280 01/02/2014 12:37:05 01/02/2014 14:36:18 280 01/02/2014 14:36:27 01/02/2014 14:49:43 280 01/02/2014 14:49:50 01/02/2014 15:47:21 280 01/02/2014 15:47:48 01/02/2014 23:30:12 280 02/02/2014 12:16:43 02/02/2014 13:15:52 365
  356. 356. SQL> select acct, ceil(max(finished_losing-started_losing)) 2 from account_txns 3 MATCH_RECOGNIZE 4 ( 5 partition by acct 6 order by tstamp 7 measures 8 tstamp as tstamp, outcome as outcome, 9 first(still_losing.tstamp) started_losing, 10 got_lucky.tstamp finished_losing 11 one row per match 12 pattern ( still_losing* got_lucky ) 13 define 14 still_losing as outcome = 'Lose' 15 and still_losing.outcome = 16 first(still_losing.outcome), 17 got_lucky as outcome = 'Win' 18 ) 19 group by acct 20 order by 1,2; 366
  357. 357. ACCT CEIL(MAX(FINISHED_LOSING-STARTED_LOSING)) ---------- ----------------------------------------- 66 3 184 7 280 2 416 1 814 3 908 5 1083 2 1142 3 1256 1 1260 1 1282 15 1676 2 1794 1 2085 12 2133 4 ... 367
  358. 358. Feature scheduler enhancements 368
  359. 359. external scripts 369
  360. 360. SQL> declare 2 l_job varchar2(100) := 3 '#!/bin/ksh 4 /bin/ps -ef > /tmp/process.out'; 5 begin 6 dbms_scheduler.create_job( 7 job_type => 'EXTERNAL_SCRIPT', 8 job_name => 'UNIX_PS', 9 job_action => l_job, 10 start_date => sysdate, 11 enabled => true); 12 end; 13 / PL/SQL procedure successfully completed. 370
  361. 361. # cat CDB12_j000_4559.trc [snip] ORA-12012: error on auto execute of job "SCOTT"."UNIX_PS" ORA-27451: CREDENTIAL_NAME cannot be NULL 371
  362. 362. SQL> begin 2 dbms_scheduler.create_credential( 3 credential_name=>'MY_ACCT', 4 username =>'unixacct', 5 password =>'unixpass'); 6 end; 7 / PL/SQL procedure successfully completed. 372
  363. 363. SQL> declare 2 l_job varchar2(100) := 3 'connect / as sysdba 4 spool /tmp/x.out 5 select * from v$database; 6 exit'; 7 begin 8 dbms_scheduler.create_job( 9 job_type => 'SQL_SCRIPT', 10 job_name => 'SQLPLUS', 11 job_action => l_job, 12 enabled => true, 13 credential_name => 'MY_ACCT' 14 ); 15 end; 16 / PL/SQL procedure successfully completed. 373
  364. 364. Feature data redaction
  365. 365. SQL> desc ACCOUNTS Name Null? Type ----------------------------- -------- ------------ ID NUMBER(8) NAME VARCHAR2(30) EMAIL_ADDRESS VARCHAR2(30) SQL> select * from ACCOUNTS; ID NAME EMAIL_ADDRESS -------- -------------------- ------------------- 1 Suzanne suzy_q@yahoo.com 2 John Smith john.smith@hotmail.com ...
  366. 366. SQL> begin 2 dbms_redact.add_policy ( 3 object_schema => user, 4 object_name => 'ACCOUNTS', 5 column_name => 'EMAIL_ADDRESS', 6 policy_name => 'diddle_email', 7 expression => 8 q'{SYS_CONTEXT('USERENV','ISDBA')='FALSE'}', 9 function_type => dbms_redact.regexp, 10 regexp_pattern => 11 dbms_redact.re_pattern_email_address, 12 regexp_replace_string => 13 dbms_redact.re_redact_email_name, 14 regexp_position => dbms_redact.re_beginning, 15 regexp_occurrence => dbms_redact.re_all 16 ); 17 end; 18 / lots of options here
  367. 367. SQL> conn scott/tiger Connected. SQL> select * from ACCOUNTS; ID NAME EMAIL_ADDRESS -------- -------------------- ------------------- 1 Suzanne xxxx@yahoo.com 2 John Smith xxxx@hotmail.com ...
  368. 368. 378 take care with clients
  369. 369. SQL> desc ACCOUNTS Name Null? Type ----------------------------- -------- ------------ ID NUMBER(8) NAME VARCHAR2(30) EMAIL_ADDRESS VARCHAR2(30)
  370. 370. SQL> declare 2 p_query varchar2(32767) 3 := 'select * from mcdonac.accounts'; 4 5 l_cur int := dbms_sql.open_cursor; 6 l_descTbl dbms_sql.desc_tab; 7 l_colCnt number; 8 begin 9 dbms_sql.parse(l_cur,p_query,dbms_sql.native); 10 dbms_sql.describe_columns(l_cur,l_colCnt,l_descTbl); 11 12 for i in 1 .. l_colCnt loop 13 dbms_output.put_line( 14 rpad(l_descTbl(i).col_name,20)|| 15 lpad(l_descTbl(i).col_max_len,6)); 16 end loop; 17 end; 18 / ID 22 NAME 30 EMAIL_ADDRESS 4000
  371. 371. 381 take care with security
  372. 372. 382
  373. 373. Feature join enhancements
  374. 374. 11.2
  375. 375. SQL> create table scott.emp2 as 2 select * from scott.emp; Table created. SQL> select * 2 from scott.emp e, 3 scott.emp2 e2, 4 scott.dept d 5 where e.deptno = d.deptno(+) 6 and e2.deptno = d.deptno(+) 7 and e.empno = e2.empno 8 / where e.deptno = d.deptno(+) * ERROR at line 5: ORA-01417: a table may be outer joined to at most one other table
  376. 376. 12c
  377. 377. SQL> select * 2 from scott.emp e, 3 scott.emp2 e2, 4 scott.dept d 5 where e.deptno = d.deptno(+) 6 and e2.deptno = d.deptno(+) 7 and e.empno = e2.empno 8 / EMPNO ENAME JOB MGR ---------- ---------- --------- ---------- 7934 MILLER CLERK 7782 ...
  378. 378. correlated inline views
  379. 379. SQL> drop table scott.DEPT_BENEFITS purge; Table dropped. SQL> create table scott.DEPT_BENEFITS as 2 select d.*, 10 benefits from scott.dept d; Table created. SQL> insert into scott.DEPT_BENEFITS 2 select d.*, 20 benefits from scott.dept d; 4 rows created.
  380. 380. SQL> select e.empno, e.deptno, d.benefits 2 from scott.emp e, 3 scott.dept_benefits d 4 where e.deptno = d.deptno 5 order by 1,3; EMPNO DEPTNO BENEFITS ---------- ---------- ---------- 7369 20 10 7369 20 20 7499 30 10 7499 30 20 7521 30 10 7521 30 20 ... ...
  381. 381. "benefits for each employee"
  382. 382. SQL> select e.empno, d.deptno, b.benefits 2 from scott.emp e, 3 ( select benefits 4 from scott.DEPT_BENEFITS d 5 where d.deptno = e.deptno 6 ) b 7 order by 1,3; where d.deptno = e.deptno * ERROR at line 5: ORA-00904: "E"."DEPTNO": invalid identifier
  383. 383. CROSS APPLY
  384. 384. SQL> select e.empno, e.deptno, b.benefits 2 from scott.emp e 3 CROSS APPLY 4 ( select benefits 5 from scott.DEPT_BENEFITS d 6 where d.deptno = e.deptno 7 ) b 8 order by 1,3; EMPNO DEPTNO BENEFITS ---------- ---------- ---------- 7369 20 10 7369 20 20 7499 30 10 ... ...
  385. 385. "big deal"
  386. 386. SQL> select e.empno, d.deptno, b.benefits 2 from scott.emp e, 3 ( select benefits 4 from scott.DEPT_BENEFITS d 5 where d.deptno = e.deptno 6 ) b 7 8 order by 1,3;
  387. 387. "best benefit for each employee"
  388. 388. SQL> select e.empno, e.deptno, b.benefits 2 from scott.emp e 3 CROSS APPLY 4 ( select benefits 5 from scott.DEPT_BENEFITS d 6 where d.deptno = e.deptno 7 order by benefits desc 8 fetch first 1 rows only 9 ) b 10 order by 1,3; EMPNO DEPTNO BENEFITS ---------- ---------- ---------- 7369 20 20 7499 30 20 7521 30 20 7566 20 20 7654 30 20 ...
  389. 389. 399 Feature anyone remember this ?
  390. 390. 400 11.2
  391. 391. 401
  392. 392. 402 "version control"
  393. 393. 403 package PKG is select COL1, COL2 from MY_VIEW package PKG(V2) is select COL1, NEW_COL from MY_VIEW(V2) both in active use !
  394. 394. 404 "edition based redefinition"
  395. 395. 405 really cool .... but
  396. 396. 406 Enabling editions is global, retroactive and irreversible. - 11g2 doc
  397. 397. 407 SQL> alter user TO_BE_EDITIONED enable editions; alter user TO_BE_EDITIONED enable editions * ERROR at line 1: ORA-38819: user TO_BE_EDITIONED owns one or more objects whose type is editionable and that have noneditioned dependent objects
  398. 398. 408 12c
  399. 399. 409 much much better
  400. 400. 410 schema is editionable...
  401. 401. 411 ...and object is editionable
  402. 402. wrap up 412
  403. 403. 12c 413
  404. 404. 414
  405. 405. Connor McDonald OracleDBA co.uk 415
  406. 406. 416 ORA-03113 @connor_mc_d connormcdonald.wordpress.com
  • venkatss2012

    Oct. 17, 2014
  • EliasNema

    Oct. 5, 2014
  • JeffreyKemp1

    Sep. 30, 2014

Slides from Openworld

Views

Total views

1,634

On Slideshare

0

From embeds

0

Number of embeds

190

Actions

Downloads

0

Shares

0

Comments

0

Likes

3

×