SlideShare ist ein Scribd-Unternehmen logo
1 von 416
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 1: 
ORA-65096: invalid common user or role name 
?
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) 
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)
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.
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 
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
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 varchar2(30) 
); 
type row_list is table of each_row 
index by pls_integer; 
g row_list; 
end; 
/
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 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; 
/
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; 
/
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
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. 
57
SQL> ALTER TABLE EMP FLASHBACK ARCHIVE LONGTERM; 
Table altered. 
58
SQL> select * from EMP; 
-------------------------------------------------- 
| Id | Operation | Name | Rows | Bytes | 
-------------------------------------------------- 
| 0 | SELECT STATEMENT | | 14 | 518 | 
| 1 | TABLE ACCESS FULL| EMP | 14 | 518 | 
-------------------------------------------------- 
59
[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
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
"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 = 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
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
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); 
Table altered. 
[etc] 
[etc] 
80
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 completed. 
83
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 '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
87
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
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
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
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
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 "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
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, 
7 end_dt DATE, 
8 
9 ); 
Table created.
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, 
7 end_dt DATE, 
8 PERIOD FOR valid_range (start_dt, end_dt) 
9 ); 
Table created.
examples
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
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
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 
------------------------------------------ 
651 recursive calls 
0 db block gets 
2243 consistent gets 
24 physical reads
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
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.
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",
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",
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
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",
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
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
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
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",
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
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 valid_range '01-FEB-14'}',:c); 
6 end; 
7 /
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"
existing tables
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.
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 ?
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
multi temporal validity
SQL> alter table EMP_TEMPORAL add period for CAL_RANGE; 
Table altered. 
SQL> alter table EMP_TEMPORAL add period for FINYR_RANGE; 
Table altered.
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, 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
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 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.
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 for valid_range '01-FEB-14' 
* 
ERROR at line 2: 
ORA-08187: snapshot expression not allowed here
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.
"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 table T set unused column Y; 
Table altered.
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$
now exposed to us
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)
and an idiosyncracy...
SQL> alter table T modify c1 visible; 
SQL> desc T 
Name Null? Type 
---------------------------- -------- ------- 
C2 NUMBER(38) 
C3 NUMBER(38) 
C1 NUMBER(38)
requires code discipline
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
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)
SQL> exec P 
PL/SQL procedure successfully completed. 
SQL> select c1,c2,c3 from t; 
C1 C2 C3 
---------- ---------- ---------- 
1 10 100 
100 1 10
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 /
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)
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 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.
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 ( 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.
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 is invalid 
ORA-06550: line 1, column 7: 
PL/SQL: Statement ignored
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.
tools
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)
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)
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 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.
178 
SQL> truncate table PARENT; 
truncate table PARENT 
* 
ERROR at line 1: 
ORA-02266: unique/primary keys in table 
referenced by enabled foreign keys
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 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
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_seq.nextval from dual; 
NEXTVAL 
---------- 
1
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> insert into GTT 
2 select NORMAL.NEXTVAL 
3 from dual 
4 connect by level < 50000; 
49999 rows created.
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
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
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
193 
but ...
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"
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 
---------- 
1 
2 
3 
4 
5 
6 
7 
8 
9 
...
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 
-------------------------- 
2000005 
... 
1000000 2000000 3000000 
not yet documented ...
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 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.
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 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
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 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
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
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 ( pk, c1 ) values (default, 1) ; 
SQL> select * from T; 
PK C1 
---------- ---------- 
2 0 
3 1
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
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); 
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
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
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
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 (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.
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 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.
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 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
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 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.
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
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.
... 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 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 /
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 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 / 
?
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 /
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
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;
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
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 /
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
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.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;
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
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 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;
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
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 / 
Package created.
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 /
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
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 !!! 
* 
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
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 
Smith
until ...
SQL> select initcap(vendor) 
2 from service_provider; 
INITCAP(VENDOR) 
------------------------------ 
Jones 
Brown 
Smith 
Mcdonald 
Johnson'S 
uh oh
home grown
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.
cool ...
SQL> select my_initcap(vendor) 
2 from service_provider; 
MY_INITCAP(VENDOR) 
-------------------------- 
Jones 
Brown 
Smith 
McDonald 
Johnson's
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) 
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
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 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
"Always code as if the person who 
ends up maintaining your code is a 
psychopathic killer who knows 
where you live." 
- source unknown
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 
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
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]|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 /
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 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);
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) 
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"
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.
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(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
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.
determinism
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 
...
DETERMINISTIC keyword
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 
...
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 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 
...
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 connect by level <= 1000 ) 
7 ; 
SUM(F) 
---------- 
1000000 
Elapsed: 00:00:02.04
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
"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 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
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 
---------- ---------- ------------------- 
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
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 <= 2; 
EMPNO ENAME HIREDATE 
---------- ---------- --------- 
7876 ADAMS 23-MAY-87 
7788 SCOTT 19-APR-87 
312
------------------------------------------------ 
| 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
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
------------------------------------------------- 
| 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
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 HIREDATE 
---------- ---------- --------- 
7876 ADAMS 23-MAY-87 
7788 SCOTT 19-APR-87 
317
behind the scenes 
318
------------------------------------------------- 
| 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
variations 
320
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
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
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
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; 
EMPNO ENAME HIREDATE 
---------- ---------- --------- 
7839 KING 17-NOV-81 
7654 MARTIN 28-SEP-81 
7844 TURNER 08-SEP-81 
325
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 rows only 
* 
ERROR at line 4: 
ORA-00905: missing keyword 
327
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
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 percent rows only; 
offset 20 percent fetch next 10 percent rows only 
* 
ERROR at line 4: 
ORA-00905: missing keyword 
330
plsql quirk 
331
"Note that in real life, 
you would use bind variables 
instead of hard-coded literals" 
332 
- Tom Kyte, 
Oracle Magazine, Sep 13
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
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
Feature 
adaptive plans
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.
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
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
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. 
SQL> commit; 
Commit complete. 
SQL> select count(*) from PARENT 
2 where p < 10; 
COUNT(*) 
---------- 
20004
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 selected 
SQL> select * 
2 from table( 
3 dbms_xplan.display_cursor( 
4 null,null,'ALLSTATS LAST +ADAPTIVE'));
----------------------------------------------------------- 
| 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 | 
-----------------------------------------------------------
----------------------------------------------------------- 
| 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 | 
-----------------------------------------------------------
----------------------------------------------------------- 
| 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 | 
-----------------------------------------------------------
----------------------------------------------------------- 
| 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 | 
-----------------------------------------------------------
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
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 different branch" 
357
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
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 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
"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 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
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
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
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
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.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
# 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
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
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
Feature 
data redaction
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 
...
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
SQL> conn scott/tiger 
Connected. 
SQL> select * from ACCOUNTS; 
ID NAME EMAIL_ADDRESS 
-------- -------------------- ------------------- 
1 Suzanne xxxx@yahoo.com 
2 John Smith xxxx@hotmail.com 
...
378 
take care with clients
SQL> desc ACCOUNTS 
Name Null? Type 
----------------------------- -------- ------------ 
ID NUMBER(8) 
NAME VARCHAR2(30) 
EMAIL_ADDRESS VARCHAR2(30)
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
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.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
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.deptno(+) 
7 and e.empno = e2.empno 
8 / 
EMPNO ENAME JOB MGR 
---------- ---------- --------- ---------- 
7934 MILLER CLERK 7782 
...
correlated inline views
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.
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 
... 
...
"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 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
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_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 
... 
...
"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 
where d.deptno = e.deptno 
6 ) b 
7 
8 order by 1,3;
"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_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 
...
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 active use !
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: 
ORA-38819: user TO_BE_EDITIONED owns one or more 
objects whose type is editionable and that have 
noneditioned dependent objects
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

Weitere ähnliche Inhalte

Was ist angesagt?

12c for Developers - Feb 2014
12c for Developers - Feb 201412c for Developers - Feb 2014
12c for Developers - Feb 2014Connor McDonald
 
了解Oracle rac brain split resolution
了解Oracle rac brain split resolution了解Oracle rac brain split resolution
了解Oracle rac brain split resolutionmaclean liu
 
11 Things About11g
11 Things About11g11 Things About11g
11 Things About11gfcamachob
 
Optimizer Cost Model MySQL 5.7
Optimizer Cost Model MySQL 5.7Optimizer Cost Model MySQL 5.7
Optimizer Cost Model MySQL 5.7I Goo Lee
 
Riyaj real world performance issues rac focus
Riyaj real world performance issues rac focusRiyaj real world performance issues rac focus
Riyaj real world performance issues rac focusRiyaj Shamsudeen
 
Advanced RAC troubleshooting: Network
Advanced RAC troubleshooting: NetworkAdvanced RAC troubleshooting: Network
Advanced RAC troubleshooting: NetworkRiyaj Shamsudeen
 
Performance tuning a quick intoduction
Performance tuning   a quick intoductionPerformance tuning   a quick intoduction
Performance tuning a quick intoductionRiyaj Shamsudeen
 
MySQL Document Store
MySQL Document StoreMySQL Document Store
MySQL Document StoreI Goo Lee
 
Fatkulin presentation
Fatkulin presentationFatkulin presentation
Fatkulin presentationEnkitec
 
Extra performance out of thin air
Extra performance out of thin airExtra performance out of thin air
Extra performance out of thin airKonstantine Krutiy
 
Dbms plan - A swiss army knife for performance engineers
Dbms plan - A swiss army knife for performance engineersDbms plan - A swiss army knife for performance engineers
Dbms plan - A swiss army knife for performance engineersRiyaj Shamsudeen
 
Oracle 10g Performance: chapter 00 sampling
Oracle 10g Performance: chapter 00 samplingOracle 10g Performance: chapter 00 sampling
Oracle 10g Performance: chapter 00 samplingKyle Hailey
 
Introduction to MySQL InnoDB Cluster
Introduction to MySQL InnoDB ClusterIntroduction to MySQL InnoDB Cluster
Introduction to MySQL InnoDB ClusterI Goo Lee
 
Drizzle to MySQL, Stress Free Migration
Drizzle to MySQL, Stress Free MigrationDrizzle to MySQL, Stress Free Migration
Drizzle to MySQL, Stress Free MigrationAndrew Hutchings
 
The Challenges of Distributing Postgres: A Citus Story
The Challenges of Distributing Postgres: A Citus StoryThe Challenges of Distributing Postgres: A Citus Story
The Challenges of Distributing Postgres: A Citus StoryHanna Kelman
 

Was ist angesagt? (20)

12c for Developers - Feb 2014
12c for Developers - Feb 201412c for Developers - Feb 2014
12c for Developers - Feb 2014
 
了解Oracle rac brain split resolution
了解Oracle rac brain split resolution了解Oracle rac brain split resolution
了解Oracle rac brain split resolution
 
Vertica trace
Vertica traceVertica trace
Vertica trace
 
11 Things About11g
11 Things About11g11 Things About11g
11 Things About11g
 
Optimizer Cost Model MySQL 5.7
Optimizer Cost Model MySQL 5.7Optimizer Cost Model MySQL 5.7
Optimizer Cost Model MySQL 5.7
 
Riyaj real world performance issues rac focus
Riyaj real world performance issues rac focusRiyaj real world performance issues rac focus
Riyaj real world performance issues rac focus
 
Advanced RAC troubleshooting: Network
Advanced RAC troubleshooting: NetworkAdvanced RAC troubleshooting: Network
Advanced RAC troubleshooting: Network
 
Rac introduction
Rac introductionRac introduction
Rac introduction
 
Performance tuning a quick intoduction
Performance tuning   a quick intoductionPerformance tuning   a quick intoduction
Performance tuning a quick intoduction
 
MySQL Document Store
MySQL Document StoreMySQL Document Store
MySQL Document Store
 
Fatkulin presentation
Fatkulin presentationFatkulin presentation
Fatkulin presentation
 
MySQL SQL Tutorial
MySQL SQL TutorialMySQL SQL Tutorial
MySQL SQL Tutorial
 
Extra performance out of thin air
Extra performance out of thin airExtra performance out of thin air
Extra performance out of thin air
 
Dbms plan - A swiss army knife for performance engineers
Dbms plan - A swiss army knife for performance engineersDbms plan - A swiss army knife for performance engineers
Dbms plan - A swiss army knife for performance engineers
 
Px execution in rac
Px execution in racPx execution in rac
Px execution in rac
 
Oracle 10g Performance: chapter 00 sampling
Oracle 10g Performance: chapter 00 samplingOracle 10g Performance: chapter 00 sampling
Oracle 10g Performance: chapter 00 sampling
 
Introduction to MySQL InnoDB Cluster
Introduction to MySQL InnoDB ClusterIntroduction to MySQL InnoDB Cluster
Introduction to MySQL InnoDB Cluster
 
Drizzle to MySQL, Stress Free Migration
Drizzle to MySQL, Stress Free MigrationDrizzle to MySQL, Stress Free Migration
Drizzle to MySQL, Stress Free Migration
 
Rac 12c optimization
Rac 12c optimizationRac 12c optimization
Rac 12c optimization
 
The Challenges of Distributing Postgres: A Citus Story
The Challenges of Distributing Postgres: A Citus StoryThe Challenges of Distributing Postgres: A Citus Story
The Challenges of Distributing Postgres: A Citus Story
 

Ähnlich wie OpenWorld Sep14 12c for_developers

11thingsabout11g 12659705398222 Phpapp01
11thingsabout11g 12659705398222 Phpapp0111thingsabout11g 12659705398222 Phpapp01
11thingsabout11g 12659705398222 Phpapp01Karam Abuataya
 
Connor McDonald 11g for developers
Connor McDonald 11g for developersConnor McDonald 11g for developers
Connor McDonald 11g for developersInSync Conference
 
Sangam 2019 - The Latest Features
Sangam 2019 - The Latest FeaturesSangam 2019 - The Latest Features
Sangam 2019 - The Latest FeaturesConnor McDonald
 
Oracle dbms_xplan.display_cursor format
Oracle dbms_xplan.display_cursor formatOracle dbms_xplan.display_cursor format
Oracle dbms_xplan.display_cursor formatFranck Pachot
 
OpenWorld 2018 - Common Application Developer Disasters
OpenWorld 2018 - Common Application Developer DisastersOpenWorld 2018 - Common Application Developer Disasters
OpenWorld 2018 - Common Application Developer DisastersConnor McDonald
 
Most important "trick" of performance instrumentation
Most important "trick" of performance instrumentationMost important "trick" of performance instrumentation
Most important "trick" of performance instrumentationCary Millsap
 
Oracle Database 12c Application Development
Oracle Database 12c Application DevelopmentOracle Database 12c Application Development
Oracle Database 12c Application DevelopmentSaurabh K. Gupta
 
Indexes From the Concept to Internals
Indexes From the Concept to InternalsIndexes From the Concept to Internals
Indexes From the Concept to InternalsDeiby Gómez
 
Understanding Query Optimization with ‘regular’ and ‘Exadata’ Oracle
Understanding Query Optimization with ‘regular’ and ‘Exadata’ OracleUnderstanding Query Optimization with ‘regular’ and ‘Exadata’ Oracle
Understanding Query Optimization with ‘regular’ and ‘Exadata’ OracleGuatemala User Group
 
Percona xtra db cluster(pxc) non blocking operations, what you need to know t...
Percona xtra db cluster(pxc) non blocking operations, what you need to know t...Percona xtra db cluster(pxc) non blocking operations, what you need to know t...
Percona xtra db cluster(pxc) non blocking operations, what you need to know t...Marco Tusa
 
HandlerSocket plugin for MySQL (English)
HandlerSocket plugin for MySQL (English)HandlerSocket plugin for MySQL (English)
HandlerSocket plugin for MySQL (English)akirahiguchi
 
12c Mini Lesson - Inline PLSQL from SQL
12c Mini Lesson - Inline PLSQL from SQL12c Mini Lesson - Inline PLSQL from SQL
12c Mini Lesson - Inline PLSQL from SQLConnor McDonald
 
Latin America Tour 2019 - 10 great sql features
Latin America Tour 2019  - 10 great sql featuresLatin America Tour 2019  - 10 great sql features
Latin America Tour 2019 - 10 great sql featuresConnor McDonald
 
UKOUG - 25 years of hints and tips
UKOUG - 25 years of hints and tipsUKOUG - 25 years of hints and tips
UKOUG - 25 years of hints and tipsConnor McDonald
 
Sangam 19 - PLSQL still the coolest
Sangam 19 - PLSQL still the coolestSangam 19 - PLSQL still the coolest
Sangam 19 - PLSQL still the coolestConnor McDonald
 
SQL Tuning 101 - Sep 2013
SQL Tuning 101 - Sep 2013SQL Tuning 101 - Sep 2013
SQL Tuning 101 - Sep 2013Connor McDonald
 
Database Management System
Database Management SystemDatabase Management System
Database Management SystemHitesh Mohapatra
 
SQL Macros - Game Changing Feature for SQL Developers?
SQL Macros - Game Changing Feature for SQL Developers?SQL Macros - Game Changing Feature for SQL Developers?
SQL Macros - Game Changing Feature for SQL Developers?Andrej Pashchenko
 

Ähnlich wie OpenWorld Sep14 12c for_developers (20)

11thingsabout11g 12659705398222 Phpapp01
11thingsabout11g 12659705398222 Phpapp0111thingsabout11g 12659705398222 Phpapp01
11thingsabout11g 12659705398222 Phpapp01
 
Connor McDonald 11g for developers
Connor McDonald 11g for developersConnor McDonald 11g for developers
Connor McDonald 11g for developers
 
Sangam 2019 - The Latest Features
Sangam 2019 - The Latest FeaturesSangam 2019 - The Latest Features
Sangam 2019 - The Latest Features
 
Oracle dbms_xplan.display_cursor format
Oracle dbms_xplan.display_cursor formatOracle dbms_xplan.display_cursor format
Oracle dbms_xplan.display_cursor format
 
OpenWorld 2018 - Common Application Developer Disasters
OpenWorld 2018 - Common Application Developer DisastersOpenWorld 2018 - Common Application Developer Disasters
OpenWorld 2018 - Common Application Developer Disasters
 
Most important "trick" of performance instrumentation
Most important "trick" of performance instrumentationMost important "trick" of performance instrumentation
Most important "trick" of performance instrumentation
 
Oracle Database 12c Application Development
Oracle Database 12c Application DevelopmentOracle Database 12c Application Development
Oracle Database 12c Application Development
 
Indexes From the Concept to Internals
Indexes From the Concept to InternalsIndexes From the Concept to Internals
Indexes From the Concept to Internals
 
Understanding Query Optimization with ‘regular’ and ‘Exadata’ Oracle
Understanding Query Optimization with ‘regular’ and ‘Exadata’ OracleUnderstanding Query Optimization with ‘regular’ and ‘Exadata’ Oracle
Understanding Query Optimization with ‘regular’ and ‘Exadata’ Oracle
 
Percona xtra db cluster(pxc) non blocking operations, what you need to know t...
Percona xtra db cluster(pxc) non blocking operations, what you need to know t...Percona xtra db cluster(pxc) non blocking operations, what you need to know t...
Percona xtra db cluster(pxc) non blocking operations, what you need to know t...
 
HandlerSocket plugin for MySQL (English)
HandlerSocket plugin for MySQL (English)HandlerSocket plugin for MySQL (English)
HandlerSocket plugin for MySQL (English)
 
12c Mini Lesson - Inline PLSQL from SQL
12c Mini Lesson - Inline PLSQL from SQL12c Mini Lesson - Inline PLSQL from SQL
12c Mini Lesson - Inline PLSQL from SQL
 
Flashback ITOUG
Flashback ITOUGFlashback ITOUG
Flashback ITOUG
 
Latin America Tour 2019 - 10 great sql features
Latin America Tour 2019  - 10 great sql featuresLatin America Tour 2019  - 10 great sql features
Latin America Tour 2019 - 10 great sql features
 
UKOUG - 25 years of hints and tips
UKOUG - 25 years of hints and tipsUKOUG - 25 years of hints and tips
UKOUG - 25 years of hints and tips
 
Sangam 19 - PLSQL still the coolest
Sangam 19 - PLSQL still the coolestSangam 19 - PLSQL still the coolest
Sangam 19 - PLSQL still the coolest
 
PHP tips by a MYSQL DBA
PHP tips by a MYSQL DBAPHP tips by a MYSQL DBA
PHP tips by a MYSQL DBA
 
SQL Tuning 101 - Sep 2013
SQL Tuning 101 - Sep 2013SQL Tuning 101 - Sep 2013
SQL Tuning 101 - Sep 2013
 
Database Management System
Database Management SystemDatabase Management System
Database Management System
 
SQL Macros - Game Changing Feature for SQL Developers?
SQL Macros - Game Changing Feature for SQL Developers?SQL Macros - Game Changing Feature for SQL Developers?
SQL Macros - Game Changing Feature for SQL Developers?
 

Mehr von Connor McDonald

Sangam 19 - Analytic SQL
Sangam 19 - Analytic SQLSangam 19 - Analytic SQL
Sangam 19 - Analytic SQLConnor McDonald
 
Sangam 19 - Successful Applications on Autonomous
Sangam 19 - Successful Applications on AutonomousSangam 19 - Successful Applications on Autonomous
Sangam 19 - Successful Applications on AutonomousConnor McDonald
 
UKOUG 2019 - SQL features
UKOUG 2019 - SQL featuresUKOUG 2019 - SQL features
UKOUG 2019 - SQL featuresConnor McDonald
 
APEX tour 2019 - successful development with autonomous
APEX tour 2019 - successful development with autonomousAPEX tour 2019 - successful development with autonomous
APEX tour 2019 - successful development with autonomousConnor McDonald
 
APAC Groundbreakers 2019 - Perth/Melbourne
APAC Groundbreakers 2019 - Perth/Melbourne APAC Groundbreakers 2019 - Perth/Melbourne
APAC Groundbreakers 2019 - Perth/Melbourne Connor McDonald
 
OOW19 - Flashback, not just for DBAs
OOW19 - Flashback, not just for DBAsOOW19 - Flashback, not just for DBAs
OOW19 - Flashback, not just for DBAsConnor McDonald
 
OOW19 - Read consistency
OOW19 - Read consistencyOOW19 - Read consistency
OOW19 - Read consistencyConnor McDonald
 
OOW19 - Slower and less secure applications
OOW19 - Slower and less secure applicationsOOW19 - Slower and less secure applications
OOW19 - Slower and less secure applicationsConnor McDonald
 
OOW19 - Killing database sessions
OOW19 - Killing database sessionsOOW19 - Killing database sessions
OOW19 - Killing database sessionsConnor McDonald
 
OOW19 - Ten Amazing SQL features
OOW19 - Ten Amazing SQL featuresOOW19 - Ten Amazing SQL features
OOW19 - Ten Amazing SQL featuresConnor McDonald
 
Latin America Tour 2019 - 18c and 19c featues
Latin America Tour 2019   - 18c and 19c featuesLatin America Tour 2019   - 18c and 19c featues
Latin America Tour 2019 - 18c and 19c featuesConnor McDonald
 
Latin America tour 2019 - Flashback
Latin America tour 2019 -  FlashbackLatin America tour 2019 -  Flashback
Latin America tour 2019 - FlashbackConnor McDonald
 
Latin America Tour 2019 - pattern matching
Latin America Tour 2019 - pattern matchingLatin America Tour 2019 - pattern matching
Latin America Tour 2019 - pattern matchingConnor McDonald
 
Latin America Tour 2019 - slow data and sql processing
Latin America Tour 2019  - slow data and sql processingLatin America Tour 2019  - slow data and sql processing
Latin America Tour 2019 - slow data and sql processingConnor McDonald
 
OG Yatra - upgrading to the new 12c+ optimizer
OG Yatra - upgrading to the new 12c+ optimizerOG Yatra - upgrading to the new 12c+ optimizer
OG Yatra - upgrading to the new 12c+ optimizerConnor McDonald
 
OG Yatra - 25 years of hints and tips
OG Yatra - 25 years of hints and tipsOG Yatra - 25 years of hints and tips
OG Yatra - 25 years of hints and tipsConnor McDonald
 
OG Yatra - Flashback, not just for developers
OG Yatra - Flashback, not just for developersOG Yatra - Flashback, not just for developers
OG Yatra - Flashback, not just for developersConnor McDonald
 
Kscope19 - Flashback: Good for Developers as well as DBAs
Kscope19 - Flashback: Good for Developers as well as DBAsKscope19 - Flashback: Good for Developers as well as DBAs
Kscope19 - Flashback: Good for Developers as well as DBAsConnor McDonald
 
Kscope19 - Understanding the basics of SQL processing
Kscope19 - Understanding the basics of SQL processingKscope19 - Understanding the basics of SQL processing
Kscope19 - Understanding the basics of SQL processingConnor McDonald
 

Mehr von Connor McDonald (20)

Sangam 19 - Analytic SQL
Sangam 19 - Analytic SQLSangam 19 - Analytic SQL
Sangam 19 - Analytic SQL
 
Sangam 19 - Successful Applications on Autonomous
Sangam 19 - Successful Applications on AutonomousSangam 19 - Successful Applications on Autonomous
Sangam 19 - Successful Applications on Autonomous
 
UKOUG 2019 - SQL features
UKOUG 2019 - SQL featuresUKOUG 2019 - SQL features
UKOUG 2019 - SQL features
 
APEX tour 2019 - successful development with autonomous
APEX tour 2019 - successful development with autonomousAPEX tour 2019 - successful development with autonomous
APEX tour 2019 - successful development with autonomous
 
APAC Groundbreakers 2019 - Perth/Melbourne
APAC Groundbreakers 2019 - Perth/Melbourne APAC Groundbreakers 2019 - Perth/Melbourne
APAC Groundbreakers 2019 - Perth/Melbourne
 
OOW19 - Flashback, not just for DBAs
OOW19 - Flashback, not just for DBAsOOW19 - Flashback, not just for DBAs
OOW19 - Flashback, not just for DBAs
 
OOW19 - Read consistency
OOW19 - Read consistencyOOW19 - Read consistency
OOW19 - Read consistency
 
OOW19 - Slower and less secure applications
OOW19 - Slower and less secure applicationsOOW19 - Slower and less secure applications
OOW19 - Slower and less secure applications
 
OOW19 - Killing database sessions
OOW19 - Killing database sessionsOOW19 - Killing database sessions
OOW19 - Killing database sessions
 
OOW19 - Ten Amazing SQL features
OOW19 - Ten Amazing SQL featuresOOW19 - Ten Amazing SQL features
OOW19 - Ten Amazing SQL features
 
Latin America Tour 2019 - 18c and 19c featues
Latin America Tour 2019   - 18c and 19c featuesLatin America Tour 2019   - 18c and 19c featues
Latin America Tour 2019 - 18c and 19c featues
 
Latin America tour 2019 - Flashback
Latin America tour 2019 -  FlashbackLatin America tour 2019 -  Flashback
Latin America tour 2019 - Flashback
 
Latin America Tour 2019 - pattern matching
Latin America Tour 2019 - pattern matchingLatin America Tour 2019 - pattern matching
Latin America Tour 2019 - pattern matching
 
Latin America Tour 2019 - slow data and sql processing
Latin America Tour 2019  - slow data and sql processingLatin America Tour 2019  - slow data and sql processing
Latin America Tour 2019 - slow data and sql processing
 
ANSI vs Oracle language
ANSI vs Oracle languageANSI vs Oracle language
ANSI vs Oracle language
 
OG Yatra - upgrading to the new 12c+ optimizer
OG Yatra - upgrading to the new 12c+ optimizerOG Yatra - upgrading to the new 12c+ optimizer
OG Yatra - upgrading to the new 12c+ optimizer
 
OG Yatra - 25 years of hints and tips
OG Yatra - 25 years of hints and tipsOG Yatra - 25 years of hints and tips
OG Yatra - 25 years of hints and tips
 
OG Yatra - Flashback, not just for developers
OG Yatra - Flashback, not just for developersOG Yatra - Flashback, not just for developers
OG Yatra - Flashback, not just for developers
 
Kscope19 - Flashback: Good for Developers as well as DBAs
Kscope19 - Flashback: Good for Developers as well as DBAsKscope19 - Flashback: Good for Developers as well as DBAs
Kscope19 - Flashback: Good for Developers as well as DBAs
 
Kscope19 - Understanding the basics of SQL processing
Kscope19 - Understanding the basics of SQL processingKscope19 - Understanding the basics of SQL processing
Kscope19 - Understanding the basics of SQL processing
 

Kürzlich hochgeladen

Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native ApplicationsWSO2
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfOrbitshub
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxRustici Software
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusZilliz
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...apidays
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...Zilliz
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...apidays
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyKhushali Kathiriya
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingEdi Saputra
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024The Digital Insurer
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...apidays
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FMESafe Software
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...DianaGray10
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Victor Rentea
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodJuan lago vázquez
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...apidays
 

Kürzlich hochgeladen (20)

Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 

OpenWorld Sep14 12c for_developers

  • 1. NOTE itty bitty fonts in this presentation SQL> exec sample_font Can you read this ? 1
  • 3. 3
  • 4.
  • 7. 7
  • 9. 9
  • 11. 2013 2014 2015 2016 2017 2018 2019 2020 2021 12c 12.1.0.2 12.2 management visibility 12c desupported "pilot"
  • 12. 1) know what’s coming 12
  • 14.
  • 15. 15 2) there's a lot in 12c !
  • 16. 16 but not widely advertised
  • 18. 18 blah blah multi tenant blah
  • 19. 19 blah blah blah
  • 20. 3) our use of the db is simpler 20
  • 21. 21 Value DB mainframe client server web soa Code 1209018910123456789
  • 22.
  • 23.
  • 27. 27
  • 28. 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 ?
  • 30. 30
  • 31. 31 or let someone else do it
  • 33. 33
  • 35. 35
  • 38. 38 we've all done it...
  • 39. 39 job to job to job...
  • 40. 40 auditing row changes
  • 41. 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)
  • 42. 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.
  • 43. 43 works but slow...
  • 44. 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
  • 45. 45 if you were diligent
  • 47. 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; /
  • 48. 48 create or replace trigger AUDIT_TRG1 before insert or update or delete on T begin t_pkg.g.delete; end; /
  • 49. 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; /
  • 50. 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; /
  • 51. 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
  • 54. a better, faster, robust version ... 54
  • 56. SQL> create tablespace SPACE_FOR_ARCHIVE 2 datafile 'C:ORACLEDB11ARCH_SPACE.DBF' 3 size 100M; Tablespace created. 56
  • 57. SQL> CREATE FLASHBACK ARCHIVE longterm 2 TABLESPACE space_for_archive 3 RETENTION 1 YEAR; Flashback archive created. 57
  • 58. SQL> ALTER TABLE EMP FLASHBACK ARCHIVE LONGTERM; Table altered. 58
  • 59. SQL> select * from EMP; -------------------------------------------------- | Id | Operation | Name | Rows | Bytes | -------------------------------------------------- | 0 | SELECT STATEMENT | | 14 | 518 | | 1 | TABLE ACCESS FULL| EMP | 14 | 518 | -------------------------------------------------- 59
  • 60. [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
  • 61. 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
  • 62. "I don't need to look back in time..." 62
  • 63. but can also be your audit ! 63
  • 64. 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
  • 65. 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
  • 66. so why didn't we ? 66
  • 68.
  • 70. can 12c help ? 70
  • 74. let 74 me repeat
  • 75. oracle feature that is free ! 75
  • 77. compression choose your cost 77 partitioning
  • 79. "yeah...but who ? where ? how ?" 79
  • 80. 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
  • 81. can 12c help ? 81
  • 83. SQL> begin 2 dbms_flashback_archive.set_context_level( 3 level=> 'ALL'); 4 end; PL/SQL procedure successfully completed. 83
  • 84. SQL> update EMP 2 set sal = sal*10 3 where empno = 7499; 1 row updated. SQL> commit; 84
  • 85. SQL> select XID from SYS_FBA_HIST_510592; XID ---------------- 09000B00C7080000 85
  • 86. 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
  • 87. 87
  • 88. 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
  • 89. 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
  • 90. 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
  • 91. 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
  • 92. so think about “total recall” 92 free in 11.2.0.4 as well
  • 97. be careful... silent errors 97
  • 98. 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
  • 99. data in the past ...
  • 100. ... to data at "any" time
  • 102. wtf
  • 104. "when" is a row valid
  • 105. 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.
  • 106. 12c part of the definition
  • 107. 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.
  • 109. 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
  • 110. 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
  • 113. what is the real query 113
  • 114. 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
  • 115. 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
  • 116. 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.
  • 117. 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",
  • 118. 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",
  • 119. 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
  • 120. 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",
  • 121. 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
  • 122. 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
  • 123. 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
  • 124. 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",
  • 125. 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
  • 126. 16 ... 126 more pages
  • 127. back to temporal validity 127
  • 128. 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 /
  • 129. 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"
  • 131. 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.
  • 132. 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 ?
  • 133. 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
  • 135. SQL> alter table EMP_TEMPORAL add period for CAL_RANGE; Table altered. SQL> alter table EMP_TEMPORAL add period for FINYR_RANGE; Table altered.
  • 136. maybe a 12.x feature ?
  • 138. 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
  • 139. add START_DT to primary key ?
  • 141. 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.
  • 143. 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
  • 144. 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.
  • 145. "Temporal validity is not supported with a multitenant container database" (12.1.0.1)
  • 147. have been there "forever"
  • 150. 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.
  • 151. 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$
  • 153. 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)
  • 155. SQL> alter table T modify c1 visible; SQL> desc T Name Null? Type ---------------------------- -------- ------- C2 NUMBER(38) C3 NUMBER(38) C1 NUMBER(38)
  • 157. 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
  • 158. 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)
  • 159. SQL> exec P PL/SQL procedure successfully completed. SQL> select c1,c2,c3 from t; C1 C2 C3 ---------- ---------- ---------- 1 10 100 100 1 10
  • 160. 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 /
  • 161. 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)
  • 162. so what's the appeal ?
  • 163. rollout new code online
  • 164. 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.
  • 166. 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.
  • 167. SQL> exec NEW_APP; 28 28 15 15 29 29 25 25 54 PL/SQL procedure successfully completed.
  • 168.
  • 169.
  • 170. 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
  • 171. 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.
  • 172. tools
  • 173. 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)
  • 174.
  • 175. 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)
  • 176. 176 Feature: better truncate
  • 177. 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.
  • 178. 178 SQL> truncate table PARENT; truncate table PARENT * ERROR at line 1: ORA-02266: unique/primary keys in table referenced by enabled foreign keys
  • 180. 180 SQL> truncate table PARENT cascade; Table truncated.
  • 181. 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
  • 184. 184 Feature session level sequence
  • 185. 185 SQL> create sequence SESS_SEQ session; Sequence created.
  • 186. 186 SQL> select sess_seq.nextval from dual; NEXTVAL ---------- 1 SQL> conn scott/tiger Connected. SQL> select sess_seq.nextval from dual; NEXTVAL ---------- 1
  • 188. 188 SQL> create sequence NORMAL cache 1000; Sequence created. SQL> alter session set sql_trace = true; Session altered.
  • 189. 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.
  • 190. 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
  • 191. 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
  • 192. 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
  • 194.
  • 195. 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"
  • 198. 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 ...
  • 199. 199
  • 200. 200 please let me know ....
  • 201. 201 perhaps more potential ...
  • 202. 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 ...
  • 204. 204 the most common ...
  • 205. 205 and the absolute worst ...
  • 206. 206 usage of triggers
  • 207. 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.
  • 208. 208 SQL> insert into T values (10,20); 1 row created. SQL> select * from T; PK C1 ---------- ---------- 1 20
  • 209. 209 we got smarter
  • 210. 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
  • 212. over rated ... for that stuff
  • 213. 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
  • 214. 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
  • 216. 216 SQL> create table T ( 2 pk number default seq.nextval, 3 c1 int); Table created. Oracle 7, June 1992
  • 217. 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
  • 218. 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
  • 221. 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
  • 222. 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
  • 223. 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
  • 226. 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.
  • 227. 227 SQL> select * from T; PK STATUS ---------- ------ 1 N 2 N 3
  • 229. 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.
  • 231. 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
  • 233. it all starts off easy
  • 234. 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.
  • 235. 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
  • 236. 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.
  • 237. ... and downhill from there
  • 238. 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 /
  • 239. SQL> exec P; BEGIN P; END; * ERROR at line 1: ORA-01476: divisor is equal to zero ORA-06512: at "SCOTT.P", line 22
  • 240. 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 / ?
  • 241. 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 /
  • 242. 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
  • 243. 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;
  • 244. 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
  • 245. 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 /
  • 246. 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
  • 249. 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;
  • 250. 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
  • 253. 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;
  • 254. 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
  • 255. value in "real world"
  • 256. SQL> create or replace package PKG is 2 procedure p; 3 procedure p1; 4 procedure p2; 5 procedure p3; 6 end; 7 / Package created.
  • 257. 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 /
  • 258. 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
  • 259. did you miss it ?
  • 260. 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
  • 266. SQL> select vendor 2 from service_provider; VENDOR ------------------------------ jones brown SMITH sigh...
  • 267. "no problem.... I'll use initcap"
  • 268. SQL> select initcap(vendor) 2 from service_provider; INITCAP(VENDOR) ------------------------------ Jones Brown Smith
  • 270. SQL> select initcap(vendor) 2 from service_provider; INITCAP(VENDOR) ------------------------------ Jones Brown Smith Mcdonald Johnson'S uh oh
  • 272. 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.
  • 274. SQL> select my_initcap(vendor) 2 from service_provider; MY_INITCAP(VENDOR) -------------------------- Jones Brown Smith McDonald Johnson's
  • 276.
  • 277. "you stupid developer... don't call PLSQL from SQL !!!!"
  • 278. 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
  • 279. it can be done in SQL
  • 280. 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
  • 281. "Always code as if the person who ends up maintaining your code is a psychopathic killer who knows where you live." - source unknown
  • 282. 12c ... user defined functions
  • 283. 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
  • 285. 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 /
  • 288. 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);
  • 289. and a blast from the past :-)
  • 290. 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"
  • 291. 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.
  • 294. 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
  • 295. 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.
  • 297. 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 ...
  • 299. 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 ...
  • 301. 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 ...
  • 302. are they really faster ?
  • 303. SQL> create or replace 2 function F return number is 3 begin 4 return 1; 5 end; 6 / Function created.
  • 304. 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
  • 305. 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
  • 306. "but what about all my PLSQL !!!"
  • 307. 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
  • 309. "5 most recently hired employees" 309
  • 310. 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
  • 312. 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
  • 313. ------------------------------------------------ | 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
  • 314. 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
  • 315. ------------------------------------------------- | 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
  • 317. 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
  • 319. ------------------------------------------------- | 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
  • 321. 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
  • 322. 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
  • 323. 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
  • 325. 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
  • 327. 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
  • 328. 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
  • 330. 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
  • 332. "Note that in real life, you would use bind variables instead of hard-coded literals" 332 - Tom Kyte, Oracle Magazine, Sep 13
  • 333. 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
  • 334. 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
  • 336. 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.
  • 337. 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
  • 338. 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
  • 339. now lets mess with it
  • 340. 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
  • 342. 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'));
  • 343. ----------------------------------------------------------- | 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 | -----------------------------------------------------------
  • 344. ----------------------------------------------------------- | 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 | -----------------------------------------------------------
  • 345. ----------------------------------------------------------- | 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 | -----------------------------------------------------------
  • 346. ----------------------------------------------------------- | 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 | -----------------------------------------------------------
  • 347. 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
  • 351. analytics ... since 8.1.6 351 median top n moving average etc
  • 354. 354
  • 355. 355
  • 356. AML 356 anti money laundering
  • 357. "Find 10 consecutive deposits in a 24 hour period, then a withdrawal within three days of the last deposit, at a different branch" 357
  • 358. 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
  • 362. 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
  • 363. "What is the longest losing streak for customers since the start of the month" 363
  • 364. 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
  • 365. 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
  • 366. 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
  • 367. 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
  • 370. 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
  • 371. # 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
  • 372. 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
  • 373. 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
  • 375. 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 ...
  • 376. 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
  • 377. SQL> conn scott/tiger Connected. SQL> select * from ACCOUNTS; ID NAME EMAIL_ADDRESS -------- -------------------- ------------------- 1 Suzanne xxxx@yahoo.com 2 John Smith xxxx@hotmail.com ...
  • 378. 378 take care with clients
  • 379. SQL> desc ACCOUNTS Name Null? Type ----------------------------- -------- ------------ ID NUMBER(8) NAME VARCHAR2(30) EMAIL_ADDRESS VARCHAR2(30)
  • 380. 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
  • 381. 381 take care with security
  • 382. 382
  • 384. 11.2
  • 385. 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
  • 386. 12c
  • 387. 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 ...
  • 389. 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.
  • 390. 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 ... ...
  • 391. "benefits for each employee"
  • 392. 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
  • 394. 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 ... ...
  • 396. 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;
  • 397. "best benefit for each employee"
  • 398. 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 ...
  • 399. 399 Feature anyone remember this ?
  • 401. 401
  • 403. 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 !
  • 404. 404 "edition based redefinition"
  • 405. 405 really cool .... but
  • 406. 406 Enabling editions is global, retroactive and irreversible. - 11g2 doc
  • 407. 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
  • 409. 409 much much better
  • 410. 410 schema is editionable...
  • 411. 411 ...and object is editionable
  • 414. 414
  • 416. 416 ORA-03113 @connor_mc_d connormcdonald.wordpress.com