You are on page 1of 168

12/18/2015

Note: Small fonts in this presentation

Can you read this ?

SQL> select sample_font


2 from dual ;

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 1

1
12/18/2015

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 3

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 4

2
12/18/2015

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 5

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 6

3
12/18/2015

don’t forget your feedback

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

don’t forget your feedback

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

4
12/18/2015

don’t forget your feedback

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

5
12/18/2015

make you more successful with Oracle

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

12c for Developers

Connor McDonald
Developer Advocate for SQL
2015

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | Oracle Confidential – Internal/Restricted/Highly Restricted

6
12/18/2015

"why bother?"

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 11

2013 2014 2016 ? 2020 2021

12c 12.1.2 12.2


12c
desupported
management
visibility

"maybe"

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

7
12/18/2015

"why bother?"
(part 2)

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 13

don’t reinvent

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

8
12/18/2015

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

there's a lot in 12c !

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 16

9
12/18/2015

but not widely advertised

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 17

multi- tenant

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 18

10
12/18/2015

multi- tenant

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 19

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 20

11
12/18/2015

"why bother?"
(part 3)

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 21

our use of the db is simpler

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 22

12
12/18/2015

Code

1985

Value

DB
Mainframe Client Web SOA
Server
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 23

Code

DB 1997

Value

Mainframe Client Web SOA


Server
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 23

13
12/18/2015

Cod
e
2013

Value

DB

Mainframe Client Web SOA


Server
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 23

Many cool things....

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 24

14
12/18/2015

...but first impressions

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 25

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 26

15
12/18/2015

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

?
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 27

be patient

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 28

16
12/18/2015

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 29

but beware

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 30

17
12/18/2015

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 31

or let us do it

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 32

18
12/18/2015

http://www.oracle.com/technetwork/community/developer-vm/index.html

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 33

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 34

19
12/18/2015

lets get started …

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 35

Feature:

total recall

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 36

20
12/18/2015

flashback data archive

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 37

"hold on !"

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 38

21
12/18/2015

11g feature !

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 39

super sunday

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 40

22
12/18/2015

super sunday

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 40

why talk about it ?

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 41

23
12/18/2015

we've all done it...

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 42

project to project to project ...

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 43

24
12/18/2015

auditing row changes

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 44

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 CHAR(1)
OWNER NOT NULL VARCHAR2(30)
OBJECT_NAME NOT NULL VARCHAR2(30)

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 45

25
12/18/2015

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;
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 46

works but slow...

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 47

26
12/18/2015

SQL> insert into T


2 select owner, object_name
3 from all_objects
4 where rownum <= 10000;

10000 rows created.

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 48

SQL> insert into T


2 insert
selectinto T
owner, object_name
3 from
select owner, all_objects
object_name
from all_objects
4 where
where rownumrownum
<= 10000 <= 10000;
call count cpu elapsed disk query current rows
10000-------
rows
Parse
created.
------
1
------- ----------
0.01 0.00
-------- --------- ----------
0 0 0
----------
0
Execute 1 3.10 3.05 88 123 10642 10000
Fetch 0 0.00 0.00 0 0 0 0
------- ------ ------- ---------- -------- --------- ---------- ----------
total 2 3.12 3.06 88 123 10642 10000

INSERT INTO T_AUDIT


VALUES (SYSDATE ,:B3 ,:B1 ,:B2 )

call count cpu elapsed disk query current rows


------- ------ ------- ---------- -------- --------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 10000 0.79 0.97 2 109 10845 10000
Fetch 0 0.00 0.00 0 0 0 0
------- ------ ------- ---------- -------- --------- ---------- ----------
total 10001 0.79 0.97 2 109 10845 10000

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 48

27
12/18/2015

if you were dilligent

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 49

package

bulk binding

3 triggers

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 50

28
12/18/2015

11g+

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 51

compound trigger

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 52

29
12/18/2015

SQL> create or replace


2 trigger AUDIT_TRG for insert or update or delete on T compound trigger
3
4 type each_row is record ( action varchar2(1),
5 owner varchar2(30),
6 object_name varchar2(30));
7 type row_list is table of each_row index by pls_integer;
8 g row_list;
9 v_action varchar2(1) :=
10 case when updating then 'U' when deleting then 'D' else 'I' end;
11
12 before statement is
13 begin
14 g.delete;
15 end before statement;
16
17 after each row is
18 begin
19 if updating or inserting then
...

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 53

...
21 g(g.count+1).owner := :new.owner;
22 g(g.count).object_name := :new.object_name;
23 else
24 g(g.count).owner := :old.owner;
25 g(g.count).object_name := :old.object_name;
26 end if;
27 end after each row;
28
29 after statement is
30 begin
31 forall i in 1 .. g.count
32 insert into T_AUDIT
33 values (sysdate,v_action,g(i).owner,g(i).object_name);
34 g.delete;
35 end after statement;
36
37 end;
38 /

Trigger created.

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 54

30
12/18/2015

a better, faster, robust version ...

61
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

flashback data archive

62
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

31
12/18/2015

SQL> create tablespace SPACE_FOR_ARCHIVE


2 datafile 'C:\ORACLE\DB12\ARCH_SPACE.DBF'
3 size 50G;

Tablespace created.

63
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

SQL> CREATE FLASHBACK ARCHIVE longterm


2 TABLESPACE space_for_archive
3 RETENTION 1 YEAR;

Flashback archive created.

64
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

32
12/18/2015

SQL> ALTER TABLE EMP FLASHBACK ARCHIVE LONGTERM;

Table altered.

[lots of DML on EMP]

65
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

SQL> select * from EMP;

--------------------------------------------------
| Id | Operation | Name | Rows | Bytes |
--------------------------------------------------
| 0 | SELECT STATEMENT | | 14 | 518 |
| 1 | TABLE ACCESS FULL| EMP | 14 | 518 |
--------------------------------------------------

66
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

33
12/18/2015

SQL> select * from EMP


2 AS OF TIMESTAMP SYSDATE-1/24;

--------------------------------------------------
| Id | Operation | Name | Rows | Bytes |
--------------------------------------------------
| 0 | SELECT STATEMENT | | 14 | 518 |
| 1 | TABLE ACCESS FULL| EMP | 14 | 518 |
--------------------------------------------------

67
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

3 days later...

68
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

34
12/18/2015

SQL> select * from EMP


2 AS OF TIMESTAMP SYSDATE-3;

-----------------------------------------------------------------
| 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 |
------------------------------------------------------------------

69
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

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

70
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

35
12/18/2015

"I dont care what EMP looked like in June"

71
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

can also be your audit !

72
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

36
12/18/2015

SQL> alter table EMP add


2 LAST_MOD 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;
73
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

SQL> select empno, ename, job, sal, comm,


2 nvl(VERSIONS_STARTTIME,LAST_MOD) TS
3 ,nvl(VERSIONS_OPERATION,'I') op
4 from EMP
5 versions between timestamp
6 timestamp '2015-02-11 20:12:00' and systimestamp
7 order by empno, ts;

EMPNO ENAME JOB SAL COMM TS O


---------- ---------- --------- ---------- ---------- ------------ -
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

74
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

37
12/18/2015

so why didn't we ?

75
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

reason 1

76
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

38
12/18/2015

"yeah...but who ? where ? how ?"

77
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

SQL> alter table EMP add UPDATED_BY varchar2(10);

Table altered.

SQL> alter table EMP add UPDATED_PGM varchar2(10);

Table altered.

[etc]

[etc]

78
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

39
12/18/2015

reason 2

79
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

40
12/18/2015

separately licensed

81
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

can 12c help ?

82
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

41
12/18/2015

1) context extension

83
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

SQL> begin
2 dbms_flashback_archive.set_context_level(
3 level=> 'ALL');
4 end;

PL/SQL procedure successfully completed.

84
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

42
12/18/2015

SQL> update EMP


2 set sal = sal*10
3 where empno = 7499;

1 row updated.

SQL> commit;

85
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

SQL> select XID from SYS_FBA_HIST_510592;

XID
----------------
09000B00C7080000

86
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

43
12/18/2015

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
WORKGROUP\XPS
SQL*Plus
87
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

...and a few other things 

88
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

44
12/18/2015

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)
89
MODULE VARCHAR2(256)
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |
OS_USER 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)
SESSION_EDITION_NAME VARCHAR2(256)
SESSION_USER VARCHAR2(256)
SESSION_USERID VARCHAR2(256)
SESSIONID VARCHAR2(256)
TERMINAL VARCHAR2(256)
SPARE VARCHAR2(256)

90
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

45
12/18/2015

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 : WORKGROUP\XPS
IDENTIFICATION_TYPE : LOCAL
INSTANCE_NAME : np12
MODULE : SQL*Plus
OS_USER : xps\hamcdc
SERVER_HOST : xps
...
91
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

SQL> select empno, ename, job, sal, comm,


2 VERSIONS_XID
3 from EMP
4 versions between timestamp
5 timestamp '2015-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

92
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

46
12/18/2015

SQL> select ...


2 from
3 ( select
4 empno, ename, job,
5 sal, comm, VERSIONS_XID
6 from EMP
7 versions between timestamp
8 timestamp '2015-02-11 20:12:00' and
9 systimestamp
10 ) e, SYS.SYS_FBA_CONTEXT_AUD a
11 where e.VERSIONS_XID = a.XID;

93
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

keep an eye on space

SYSTEM tablespace

94
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

47
12/18/2015

2) about that price...

95
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

flashback data archive is now …

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 89

48
12/18/2015

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 90

not a typo

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 91

49
12/18/2015

basic versus advanced

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 92

compression

choose your cost

partitioning

100
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

50
12/18/2015

so think about FDA

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 94

secure

read only

102
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

51
12/18/2015

efficient

fdba

103
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

all of your history...

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 97

52
12/18/2015

all of your audit...

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 98

"Gee...thanks"

106
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

53
12/18/2015

"Its a bit late now"

107
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

You can convert

108
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

54
12/18/2015

DBMS_FLASHBACK_ARCHIVE.IMPORT_HISTORY

109
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

be careful...

110
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

55
12/18/2015

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"

111
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

Feature:

better truncate

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 105

56
12/18/2015

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.

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 106

SQL> truncate table PARENT;

truncate table PARENT


*
ERROR at line 1:
ORA-02266: unique/primary keys in table referenced by
enabled foreign keys

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 107

57
12/18/2015

SQL> create table CHILD


2 ( c int primary key,
3 p int references PARENT ( p )
4 on delete cascade);

Table created.

SQL> insert into PARENT values (1);


SQL> insert into CHILD values (1,1);

SQL> truncate table PARENT;


truncate table PARENT
*
ERROR at line 1:
ORA-02266: unique/primary keys in table referenced by
enabled foreign keys

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 108

SQL> alter table CHILD disable constraint CHILD_FK;

SQL> truncate table CHILD;

SQL> truncate table PARENT;

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 109

58
12/18/2015

SQL> alter table CHILD disable constraint CHILD_FK;

SQL> truncate table CHILD;

SQL> truncate table PARENT;

SQL> alter table CHILD enable constraint CHILD_FK;

ERROR at line 1:
ORA-02298: cannot enable CHILD_FK - parent keys not found

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 109

12c

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 110

59
12/18/2015

SQL> truncate table PARENT cascade;

Table truncated.

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 111

must be on delete cascade

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 112

60
12/18/2015

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

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 113

full cascade

be careful

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 114

61
12/18/2015

referential partitions

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 115

Feature

session level sequence

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 116

62
12/18/2015

SQL> create sequence SESS_SEQ session;

Sequence created.

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 117

SQL> select sess_seq.nextval from dual;

NEXTVAL
----------
1

SQL> conn scott/tiger


Connected.

SQL> select sess_seq.nextval from dual;

NEXTVAL
----------
1

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 118

63
12/18/2015

"big deal"

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 119

"bad" reason

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 120

64
12/18/2015

SQL> select X SQL> select X


2 from GTT; 2 from GTT;

X X
---------- ----------
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
... ...

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 121

better reason

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 122

65
12/18/2015

contention

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 123

SQL> create sequence NORMAL cache 1000;

Sequence created.

SQL> alter session set sql_trace = true;

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.


Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 124

66
12/18/2015

insert into GTT


select NORMAL.NEXTVAL
from dual
connect by level < 50000

call count cpu elapsed disk query current rows


------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.35 0.35 0 147 642 49999
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 2 0.35 0.35 0 147 642 49999

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 125

insert into GTT


select SESS_SEQ.NEXTVAL
from dual
connect by level < 50000

call count cpu elapsed disk query current rows


------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.25 0.25 0 145 592 49999
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 2 0.25 0.25 0 145 592 49999

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 126

67
12/18/2015

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 current rows


------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 50 0.00 0.00 0 50 103 50
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 51 0.00 0.00 0 50 103 50

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 127

but still … really ?

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 128

68
12/18/2015

the importance of community

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 129

other 12c feature

DBA

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 130

69
12/18/2015

temporary undo

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 131

temporary undo
+
session sequences
+
active dataguard

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 132

70
12/18/2015

read/write GTT in DataGuard !

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 133

Feature:

defaults

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 134

71
12/18/2015

the most common ...

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 135

and the absolute worst ...

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 136

72
12/18/2015

usage of triggers

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 137

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.

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 138

73
12/18/2015

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
:new.pk into :new.pk from dual;
:= seq.nextval;
7 end;
8 /

Trigger created.

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 138

SQL> insert into T values (10,20);

1 row created.

SQL> select * from T;

PK C1
---------- ----------
1 20

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 139

74
12/18/2015

we got smarter

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 140

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

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 141

75
12/18/2015

triggers

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

over rated ...

for that stuff

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

76
12/18/2015

insert /* with trigger */ into T


select rownum, rownum
from dual connect by level <= 50000

call count cpu elapsed disk query current rows


------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 5.64 5.64 0 466 1608 50000
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 2 5.64 5.65 0 466 1608 50000

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

insert /* without trigger */ into T


select rownum, rownum
from dual connect by level <= 50000

call count cpu elapsed disk query current rows


------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.09 0.15 0 466 1620 50000
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 2 0.09 0.15 0 466 1620 50000

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

77
12/18/2015

12c ... finally !

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

SQL> create table T ( pk number default seq.nextval ,


2 c1 int);

June 1992
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 147

78
12/18/2015

SQL> insert into T ( c1 ) values (0);

SQL> select * from T;

PK C1
---------- ----------
2 0

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 148

SQL> insert into T ( pk, c1 ) values (default, 1) ;

SQL> select * from T;

PK C1
---------- ----------
2 0
3 1

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 149

79
12/18/2015

insert /* with default */ into T


select rownum, rownum
from dual connect by level <= 50000

call count cpu elapsed disk query current rows


------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.06 0.07 0 467 1608 50000
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 2 0.06 0.08 0 467 1608 50000

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

other default improvements

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

80
12/18/2015

identity

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

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

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 153

81
12/18/2015

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

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 154

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

can choose
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 155

82
12/18/2015

more null control

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

before 12c

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

83
12/18/2015

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.

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 158

SQL> select * from T;

PK STATUS
---------- ------
1 N
2 N
3

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 159

84
12/18/2015

workarounds unpleasant

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 160

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.

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 161

85
12/18/2015

12c "on null"

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

SQL> create table T (


2 pk int,
3 status varchar2(1) default on null 'N' ,
4 start_date date default on null sysdate,
5 commission int default on null 1000,
6 job_level int default on null 1
7 );

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

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 163

86
12/18/2015

Feature

query expansion

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 164

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

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 165

87
12/18/2015

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

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 166

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.

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 167

88
12/18/2015

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",
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 168
DECODE(BITAND("A4"."SEGMENT_FLAGS",131072),131072,
"A4"."BLOCKS",DECODE(BITAND("A4"."SEGMENT_FLAGS",1),1,

"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",Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 169

DECODE("A4"."BUFFER_POOL_ID",1,'KEEP',2,'RECYCLE','DEFAULT') "BUFFER_POOL",

89
12/18/2015

"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'
),NULL))
"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"
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 170
."GROUPS",0,1,
"A195"."GROUPS")) "FREELIST_GROUPS",

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 Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 171
"A206"."TYPE#"=7 OR

90
12/18/2015

"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", Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 172

"SYS"."FILE$" "A194" WHERE "A195"."FILE#"="A196"."HEADER_FILE" AND

"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("A1
90"."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", Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 173

"A191"."US#" "SEGMENT_OBJD" FROM "SYS"."USER$" "A193","SYS"."TS$" "A192",

91
12/18/2015

"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",
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 174

"A186"."MINEXTS" "MIN_EXTENTS",

"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
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 175

ODE("A182"."LISTS",0,1,

92
12/18/2015

"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", Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 176

"A6"."MTIME" "LAST_DDL_TIME",TO_CHAR("A6"."STIME",'YYYY-MM-DD:HH24:MI:SS') "TIMESTAMP",DEC

16 ...

more

pages

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 177

93
12/18/2015

Feature

PL/SQL debugging

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

it all starts off easy

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 179

94
12/18/2015

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 = 'NUTHIN';
12
13 x := x / y;
14
15 select rownum
16 into x
17 from dual;
18
19 end;
20 /

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 180

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

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 181

95
12/18/2015

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 /

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 182

... and downhill from there

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

96
12/18/2015

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 /
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 184

SQL> exec P;
BEGIN P; END;

*
ERROR at line 1:
ORA-01476: divisor is equal to zero
ORA-06512: at "SCOTT.P", line 22

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

97
12/18/2015

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 /
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 186

SQL> create or replace procedure P is


2 x int;
3 y int;
4 begin
5
6 x := 10;
7

...

18
19 exception
20 when others then
21 dbms_output.put_line(
22 dbms_utility.format_call_stack);
23 raise;
24 end;
25 /

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

98
12/18/2015

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

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 188

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 Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

26 dbms_output.put_line(l_debug);

99
12/18/2015

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

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 190

----- PL/SQL Call Stack -----


object line object
handle number name
0x14b1e3900 16 procedure SCOTT.P
0x12521b8d8 1 anonymous block

----- PL/SQL Call Stack -----\n object line object\n handle number name ...

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 191

100
12/18/2015

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 /

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

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

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 193

101
12/18/2015

10g got better

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

DBMS_UTILITY.FORMAT_ERROR_BACKTRACE

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 195

102
12/18/2015

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;

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

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

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 197

103
12/18/2015

still parsing strings

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

12c .... a better way

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 199

104
12/18/2015

UTL_CALL_STACK

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

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;

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 201

105
12/18/2015

SQL> exec P;

16-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

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

value in real world

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 203

106
12/18/2015

SQL> create or replace package PKG is


2 procedure p;
3 procedure p1;
4 procedure p2;
5 procedure p3;
6 end;
7 /

Package created.

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

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; Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 205
37 /

107
12/18/2015

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

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

did you miss it ?

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 207

108
12/18/2015

SQL> exec pkg.p3

23-PKG.P subprogram !!!


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

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

Feature

inline PLSQL in SQL

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 209

109
12/18/2015

every system ...

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

... I've worked on

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 211

110
12/18/2015

struggles with cAsE

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

no correlation 

but its my fault

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 213

111
12/18/2015

SQL> select surname


2 from names;

SURNAME
------------------------------
jones
brown
SMITH

sigh...

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

"no problem.... I'll use initcap"

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 215

112
12/18/2015

SQL> select initcap(surname)


2 from names;

INITCAP(SURNAME)
------------------------------
Jones
Brown
Smith

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

until ...

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 217

113
12/18/2015

SQL> select initcap(surname)


2 from names;

INITCAP(SURNAME)
------------------------------
Jones
Brown
Smith
Mcdonald
Johnson'S

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

home grown

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 219

114
12/18/2015

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 /

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

cool ...

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 221

115
12/18/2015

SQL> select my_initcap(surname)


2 from names;

MY_INITCAP(SURNAME)
--------------------------
Jones
Brown
Smith
McDonald
Johnson's

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

until ...

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 223

116
12/18/2015

DBA

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 224

"don't call PLSQL from SQL !!!!"

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 225

117
12/18/2015

SQL> select max(x)


2 from (
3 select /*+ no_merge */ initcap(text_col) x
4 from BIG_TABLE_100K
5 );

...

Elapsed: 00:00:00.48

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

SQL> select max(x)


2 from (
3 select /*+ no_merge */ initcap(text_col) x
4 from BIG_TABLE_100K
5 );
SQL> select max(x)
2 from (
...3 select /*+ no_merge */ my_initcap(text_col) x
4 from BIG_TABLE_100K
Elapsed:
5 ); 00:00:00.48

Elapsed: 00:00:09.37

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

118
12/18/2015

it can be done in SQL

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 227

SQL> select
2 case
3 when regexp_like(surname,'(Mac[A-Z]|Mc[A-Z])') then surname
4 when surname like '''%' then surname
5 when initcap(surname) like '_''S%' then surname
6 else replace(initcap(surname),'''S','''s')
7 end ugh
8 from names;

UGH
-------------------------------
Jones
Brown
Smith
McDonald
Johnson's

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

119
12/18/2015

"Always code as if the person who ends up


maintaining your code is a psychopathic killer
who knows where you live."
- anon

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 230

12c ... user defined functions

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

120
12/18/2015

SQL> WITH
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
...
17
18 return l_string;
19 end;
20 select my_initcap(surname)
21 from names;

MY_INITCAP(SURNAME)
-----------------------------------------
Jones
Brown
Smith
McDonald

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 232

multiple routines

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

121
12/18/2015

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

..

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 234

note: 12c client

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 235

122
12/18/2015

11.2 and below

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

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);
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 237

123
12/18/2015

workaround

SQL> set SQLTERMINATOR ...

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 238

and a little embarrassingly…

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

124
12/18/2015

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(surname)
24 from names;
25 begin
26 null;
27 end;
28 /

Warning: Procedure created with compilation errors.

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 240

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(surname)
26 from names;
27 }';
28 end;
29 /

Procedure created.

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

125
12/18/2015

WITH_PLSQL

unrelated to previous

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 242

DML (or complex SQL)

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

126
12/18/2015

SQL> insert into NAMES2


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 /

WITH
*
ERROR at line 2:
ORA-32034: unsupported use of WITH clause

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 244

SQL> insert /*+ WITH_PLSQL */ into NAMES2


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.

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

127
12/18/2015

determinism

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 246

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
...

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

128
12/18/2015

DETERMINISTIC keyword

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 248

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
...

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

129
12/18/2015

conventional scalar caching

no no no!

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 250

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
...

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

130
12/18/2015

are they really faster ?

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 252

SQL> create or replace


2 function F return number is
3 begin
4 return 1;
5 end;
6 /

Function created.

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

131
12/18/2015

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 ;

Elapsed: 00:00:02.04

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 254

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 /

Elapsed: 00:00:00.52

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

132
12/18/2015

"but what about all my PLSQL ?"

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 256

SQL> create or replace


2 function F return number is
3 pragma udf;
4 begin
5 return 1;
6 end;
7 /

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 ;

Elapsed: 00:00:00.36
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

133
12/18/2015

Feature

JSON

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

ACCOUNTING,KING,PRESIDENT,5000
ACCOUNTING,MILLER,CLERK,1300

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

134
12/18/2015

ACCOUNTING,KING,PRESIDENT,5000
ACCOUNTING,MILLER,CLERK,1300

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

<department name="ACCOUNTING">
<employees>
<employee>
<ename>KING</ename>
<job>PRESIDENT</job>
<sal>5000</sal>
</employee>
<employee>
<ename>MILLER</ename>
<job>CLERK</job>
<sal>1300</sal>
</employee>
</employees>
</department>

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

135
12/18/2015

<department name="ACCOUNTING">
<employees>
<employee>
<ename>KING</ename>
<job>PRESIDENT</job>
<sal>5000</sal>
</employee>
<employee>
<ename>MILLER</ename>
<job>CLERK</job>
<sal>1300</sal>
</employee>
</employees>
</department>

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

{ "NAME" :"ACCOUNTING"
, "EMPLOYEES" : [
{"ENAME" : "KING",
"JOB" : "PRESIDENT",
"SAL" : 5000
},
{"ENAME" : "MILLER",
"JOB" : "CLERK",
"SAL" : 1300
}]
}

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

136
12/18/2015

{ Name : Value }

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

{
Name : Value,
Name : Value,
Name : Value
}

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

137
12/18/2015

{
{
Name : Value,
Name : Value,
Name : Value
}
,
{
Name : Value,
Name : Value,
Name : Value
}
}
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

create table T
( id number(10),
my_doc varchar2(4000)
)

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

138
12/18/2015

alter table T
add constraint t_chk
check
(
my_doc is JSON
)

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

SQL> insert into T


2 values (1,
3 '{ "SomeValid" : "json" }'
4 );

1 row inserted.

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

139
12/18/2015

SQL> insert into T


2 values (2,
3 'some junk'
4 );

ORA-02290: check constraint (T_CHK) violated

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

extraction

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

140
12/18/2015

SQL> select json_value(my_doc,'$.SomeValid') tag


2 from t;

TAG
------
json

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

SQL> insert into T values (2,


2 '{ "ACCOUNTING" : {
3 "EMPLOYEES" : [
4 {"ENAME" : "KING",
5 "JOB" : "PRESIDENT",
6 "SAL" : 5000
7 },
8 {"ENAME" : "MILLER",
9 "JOB" : "CLERK",
10 "SAL" : 1300
11 }]
12 }
13 }');

1 row created.

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

141
12/18/2015

SQL> select json_value(my_doc,


2 '$.ACCOUNTING.EMPLOYEES[0].ENAME') as ename
3 from t;

ENAME
----------
KING

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

SQL> select json_query(my_doc,


2 '$.*.EMPLOYEES') as result
3 from T
4 /

RESULT
---------
[{"ENAME":"KING","JOB":"PRESIDENT","SAL":5000},{"ENAME":
"MILLER","JOB":"CLERK","SAL":1300}]

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

142
12/18/2015

dot notation

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

SQL> select t.my_doc.ACCOUNTING.EMPLOYEES.ENAME emps,


2 t.my_doc.ACCOUNTING.EMPLOYEES.JOB jobs,
3 t.my_doc.ACCOUNTING.EMPLOYEES.SAL sals
4 from T t;

EMPS JOBS SALS


-------------------- ------------------- ---------------
[KING,MILLER] [PRESIDENT,CLERK] [5000,1300]

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

143
12/18/2015

transformation

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

SQL> select ename, job, sal


2 from t,
3 json_table(my_doc,'$.ACCOUNTING.EMPLOYEES[*]'
4 columns(ename varchar2(20) path '$.ENAME',
5 job varchar2(20) path '$.JOB',
6 sal number path '$.SAL'
7 ));

ENAME JOB SAL


-------------------- -------------------- ----------
KING PRESIDENT 5000
MILLER CLERK 1300

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

144
12/18/2015

searching

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

SQL> select count(*)


2 from T
3 where json_exists(my_doc,'$.*.EMPLOYEES');

COUNT(*)
----------
1

SQL> select count(*)


2 from T
3 where my_doc is json;

COUNT(*)
----------
1

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

145
12/18/2015

search (performance)

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

1) function based indexes

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

146
12/18/2015

SQL> create index IX on T (


2 json_value(my_doc,
3 '$.ACCOUNTING.EMPLOYEES.ENAME'

4 )
5 );

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

SQL> create index IX on T (


2 json_value(my_doc,
3 '$.ACCOUNTING.EMPLOYEES.ENAME'
RETURNING VARCHAR2(20)
4 )
5 );

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

147
12/18/2015

2) text indexes

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

SQL> CREATE INDEX t_ix ON t (my_doc)


2 INDEXTYPE IS CTXSYS.CONTEXT
3 PARAMETERS ('section group CTXSYS.JSON_SECTION_GROUP');

SQL> SELECT COUNT(*)


2 FROM T
3 WHERE JSON_TEXTCONTAINS(my_doc,
4 '$.ACCOUNTING.EMPLOYEES.ENAME',
5 'KING');

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

148
12/18/2015

Feature

invisible columns

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 285

have been there "forever"

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 286

149
12/18/2015

function based indexes

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 287

set column unused

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 288

150
12/18/2015

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.

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 289

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$

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 290

151
12/18/2015

now exposed to us

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 291

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)

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 292

152
12/18/2015

and an idiosyncracy...

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 293

SQL> alter table T modify c1 visible;

SQL> desc T

Name Null? Type


---------------------------- -------- -------
C2 NUMBER(38)
C3 NUMBER(38)
C1 NUMBER(38)

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 294

153
12/18/2015

requires discipline

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 295

SQL> create or replace


2 procedure P is
3 begin
4 insert into T
5 values (1,10,100);
6 end;
7 /

Procedure created.

SQL> exec P

PL/SQL procedure successfully completed.

SQL> alter table T modify c1 invisible;

Table altered.

SQL> alter table T modify c1 visible;

Table altered.
Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 296

154
12/18/2015

SQL> exec P

PL/SQL procedure successfully completed.

SQL> select * from T;

C2 C3 C1
---------- ---------- ----------
10 100 1
1 10 100

SQL> desc T

Name Null? Type


------------------- -------- --------------------
C2 NUMBER(38)
C3 NUMBER(38)
C1 NUMBER(38)

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 297

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 / Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 298

155
12/18/2015

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)

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 299

so what's the appeal ?

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 300

156
12/18/2015

rollout changes online

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 301

SQL> create table T ( c1 int, c2 int ) ;

Table created.

SQL> create or replace


2 procedure APP1 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 APP1;

PL/SQL procedure successfully completed.

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 302

157
12/18/2015

new application

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 303

SQL> alter table T add c3 int;

Table altered.

SQL> create or replace


2 procedure APP2 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.

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 304

158
12/18/2015

SQL> exec APP2;

28
28
15
15
29
29
25
25
54

PL/SQL procedure successfully completed.

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 305

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 306

159
12/18/2015

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

SQL> exec APP1

BEGIN APP1; END;

*
ERROR at line 1:
ORA-06550: line 1, column 7:
PLS-00905: object SCOTT.APP1 is invalid
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 308

160
12/18/2015

SQL> alter table T modify c3 invisible;

Table altered.

SQL> exec APP2;

28
28
15
[snip]

PL/SQL procedure successfully completed.

SQL> exec APP1;

PL/SQL procedure successfully completed.

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 309

tools

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 310

161
12/18/2015

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)

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 311

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 312

162
12/18/2015

SQL> alter table T add "C3 (INVISIBLE)" int;

Table altered.

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 313

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)

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 313

163
12/18/2015

use LHS

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 314

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 315

164
12/18/2015

Wrap up

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 412

there's a lot in 12c

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 413

165
12/18/2015

lots not covered today

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 414

But still plenty to excite

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 415

166
12/18/2015

Monday,15:10, SQL features, Hall 1

Tuesday, 11:20, Flashback, Hall 1

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. | 416

Connor McDonald

417 Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

167
12/18/2015

ORA-03113

417 Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

Creative Commons Image Resources

https://commons.wikimedia.org/wiki/File:Horse_Race_Finish_Line_(11888565543).jpg
https://pixabay.com/en/iphone-iphone-6-apple-flat-762044/
https://pixabay.com/en/curve-return-pass-road-384406/
https://pixabay.com/en/high-five-figure-man-blue-150911/
https://pixabay.com/en/joker-jester-card-playing-card-164030/
https://commons.wikimedia.org/wiki/File:2008-08-19_Flat_tire.jpg

Copyright © 2015, Oracle and/or its affiliates. All rights reserved. |

168

You might also like