Feb14 12c for developers

1,539 views

Published on

Slides from Oracle Developer Day Perth

Published in: Technology
0 Comments
4 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,539
On SlideShare
0
From Embeds
0
Number of Embeds
6
Actions
Shares
0
Downloads
0
Comments
0
Likes
4
Embeds 0
No embeds

No notes for slide

Feb14 12c for developers

  1. 1. NOTE itty bitty fonts in this presentation SQL> exec sample_font Can you read this ? 1
  2. 2. Connor McDonald OracleDBA co.uk 2
  3. 3. 3
  4. 4. bio slide 4
  5. 5. Connor McDonald
  6. 6. Connor McDonald
  7. 7. Connor McDonald
  8. 8. Connor McDonald
  9. 9. 6
  10. 10. "why bother?" 7
  11. 11. 2013 12c 2014 12.1.2 2015 2016 2017 2018 2019 2020 2021 12.2 12c desupported management visibility "maybe"
  12. 12. 9
  13. 13. "why bother?" (part 2) 10
  14. 14. don’t reinvent
  15. 15. there's a lot in 12c ! 13
  16. 16. but not widely advertised 14
  17. 17. multi- tenant 15
  18. 18. multi- tenant 16
  19. 19. some cool things.... 17
  20. 20. some not so cool things.... 18
  21. 21. first impressions 19
  22. 22. tough for "home" exploring 20
  23. 23. 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 ? 21
  24. 24. be patient 22
  25. 25. 23
  26. 26. or let someone else do it 24
  27. 27. http://www.oracle.com/technetwork/community/developer-vm/index.html 25
  28. 28. 26
  29. 29. "Feature:" total recall 27
  30. 30. "hold on !" 28
  31. 31. 11g feature ! 29
  32. 32. why talk about it ? 31
  33. 33. we've all done it... 32
  34. 34. site to site to site... 33
  35. 35. auditing row changes 34
  36. 36. SQL> desc T Name ----------------------------OWNER OBJECT_NAME Null? -------NOT NULL NOT NULL Type ------------VARCHAR2(30) VARCHAR2(30) SQL> desc T_AUDIT Name ----------------------------AUDIT_DATE AUDIT_ACTION OWNER OBJECT_NAME Null? Type -------- -------------DATE CHAR(1) NOT NULL VARCHAR2(30) NOT NULL VARCHAR2(30) 35
  37. 37. SQL> 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 create or replace trigger AUDIT_TRG after insert or update or delete on T for each row declare v_action varchar2(1) := case when updating then 'U' when deleting then 'D' else 'I' end; begin if updating or inserting then insert into T_AUDIT values (sysdate ,v_action ,:new.owner ,:new.object_name); else insert into T_AUDIT values (sysdate ,v_action ,:old.owner ,:old.object_name); end if; end; / Trigger created. 36
  38. 38. works but slow... 37
  39. 39. SQL> 2 3 4 insert select from where into T owner, object_name all_objects rownum <= 10000; 10000 rows created. 38
  40. 40. SQL> insert 2 select 3 from insert where 4 into T into T owner, object_name all_objects rownum <= 10000; select owner, object_name from all_objects 10000 rownum <= 10000 rows created. where call count ------- -----Parse 1 Execute 1 Fetch 0 ------- -----total 2 cpu elapsed disk query current ------- ---------- -------- --------- ---------0.01 0.00 0 0 0 3.10 3.05 88 123 10642 0.00 0.00 0 0 0 ------- ---------- -------- --------- ---------3.12 3.06 88 123 10642 rows ---------0 10000 0 ---------10000 INSERT INTO T_AUDIT VALUES (SYSDATE ,:B3 ,:B1 ,:B2 ) call count ------- -----Parse 1 Execute 10000 Fetch 0 ------- -----total 10001 cpu elapsed disk query current ------- ---------- -------- --------- ---------0.00 0.00 0 0 0 0.79 0.97 2 109 10845 0.00 0.00 0 0 0 ------- ---------- -------- --------- ---------0.79 0.97 2 109 10845 rows ---------0 10000 0 ---------10000 38
  41. 41. if you were dilligent 39
  42. 42. bulk binding see later 40
  43. 43. 11g 41
  44. 44. compound triggers 42
  45. 45. a better, faster, robust version ... 49
  46. 46. ... total recall 11g 50
  47. 47. SQL> create tablespace SPACE_FOR_ARCHIVE 2 datafile 'C:ORACLEDB11ARCH_SPACE.DBF' 3 size 100M; Tablespace created. 51
  48. 48. SQL> CREATE FLASHBACK ARCHIVE longterm 2 TABLESPACE space_for_archive 3 RETENTION 1 YEAR; Flashback archive created. 52
  49. 49. SQL> ALTER TABLE EMP FLASHBACK ARCHIVE LONGTERM; Table altered. [lots of DML] 53
  50. 50. SQL> select * from EMP; -------------------------------------------------| Id | Operation | Name | Rows | Bytes | -------------------------------------------------| 0 | SELECT STATEMENT | | 14 | 518 | | 1 | TABLE ACCESS FULL| EMP | 14 | 518 | -------------------------------------------------- 54
  51. 51. SQL> select * from EMP 2 AS OF TIMESTAMP SYSDATE-3; -------------------------------------------------| Id | Operation | Name | Rows | Bytes | -------------------------------------------------| 0 | SELECT STATEMENT | | 14 | 518 | | 1 | TABLE ACCESS FULL| EMP | 14 | 518 | -------------------------------------------------- 55
  52. 52. [after DML and time passing] 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 | ------------------------------------------------------------------ 56
  53. 53. 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 57
  54. 54. but can also be your audit ! 58
  55. 55. 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; 59
  56. 56. SQL> 2 3 4 5 6 7 8 select empno, ename, job, sal, comm, nvl(VERSIONS_STARTTIME,LAST_MOD) TS ,nvl(VERSIONS_OPERATION,'I') op from EMP versions between timestamp timestamp '2014-02-11 20:12:00' and systimestamp order by empno; EMPNO ---------7369 7369 7499 7521 7566 ... 7900 7902 7934 7934 ENAME ---------SMITH SMITH ALLEN WARD JONES JOB SAL COMM TS --------- ---------- ---------- -----------CLERK 806 08.10.51 PM SALES 8060 1000 08.12.10 PM SALESMAN 1606 300000000 08.10.51 PM SALESMAN 1256 500000000 08.10.51 PM MANAGER 2981 08.10.51 PM O I U I I I JAMES FORD MILLER MILLER CLERK ANALYST CLERK CLERK I I I D 956 3006 1306 1306 08.10.51 08.10.51 08.10.51 08.12.10 PM PM PM PM 60
  57. 57. so why didn't we ? 61
  58. 58. reason 1 62
  59. 59. "yeah...but who ? where ? how ?" 63
  60. 60. SQL> alter table EMP add UPDATED_BY varchar2(10); Table altered. SQL> alter table EMP add UPDATED_PGM varchar2(10); Table altered. [etc] [etc] 64
  61. 61. reason 2 65
  62. 62. separately licensed :-( 67
  63. 63. can 12c help ? 68
  64. 64. 1) context extension 69
  65. 65. SQL> begin 2 dbms_flashback_archive.set_context_level( 3 level=> 'ALL'); 4 end; PL/SQL procedure successfully completed. 70
  66. 66. SQL> update EMP 2 set sal = sal*10 3 where empno = 7499; 1 row updated. SQL> commit; 71
  67. 67. SQL> select XID from SYS_FBA_HIST_510592; XID ---------------09000B00C7080000 72
  68. 68. 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 73
  69. 69. 74
  70. 70. SQL> desc SYS.SYS_FBA_CONTEXT_AUD Name Null? ------------------------- -------XID ACTION AUTHENTICATED_IDENTITY CLIENT_IDENTIFIER CLIENT_INFO CURRENT_EDITION_NAME CURRENT_SCHEMA CURRENT_USER DATABASE_ROLE DB_NAME GLOBAL_UID HOST IDENTIFICATION_TYPE INSTANCE_NAME IP_ADDRESS MODULE OS_USER SERVER_HOST SERVICE_NAME Type -----------------RAW(8) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) 75
  71. 71. AUTHENTICATED_IDENTITY CLIENT_IDENTIFIER CLIENT_INFO CURRENT_EDITION_NAME CURRENT_SCHEMA CURRENT_USER DATABASE_ROLE DB_NAME GLOBAL_UID HOST IDENTIFICATION_TYPE INSTANCE_NAME IP_ADDRESS MODULE OS_USER SERVER_HOST SERVICE_NAME SESSION_EDITION_NAME SESSION_USER SESSION_USERID SESSIONID TERMINAL SPARE VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) VARCHAR2(256) 76
  72. 72. SQL> @pt "select * from SYS.SYS_FBA_CONTEXT_AUD where xid = '09000B00C7080000'" XID AUTHENTICATED_IDENTITY CLIENT_IDENTIFIER CLIENT_INFO CURRENT_EDITION_NAME CURRENT_SCHEMA CURRENT_USER DATABASE_ROLE DB_NAME HOST IDENTIFICATION_TYPE INSTANCE_NAME MODULE OS_USER SERVER_HOST SERVICE_NAME SESSION_EDITION_NAME SESSION_USER SESSION_USERID SESSIONID TERMINAL : : : : : : : : : : : : : : : : : : : : : 09000B00C7080000 scott ORA$BASE SYS SYS PRIMARY np12 WORKGROUPXPS LOCAL np12 SQL*Plus xpshamcdc xps SYS$USERS ORA$BASE SCOTT 103 230698 XPS 77
  73. 73. SQL> 2 3 4 5 6 7 select empno, ename, job, sal, comm, VERSIONS_XID from EMP versions between timestamp timestamp '2014-02-11 20:12:00' and systimestamp order by empno; EMPNO ---------7369 7369 7499 7499 7499 7521 ENAME ---------SMITH SMITH ALLEN ALLEN ALLEN WARD JOB SAL COMM VERSIONS_XID --------- ---------- ---------- ---------------CLERK 806 SALES 8060 1000 09001C00E04A0000 CLERK 16060 300000000 0A000A0024080000 SALESMAN 16060 300000000 09000B00C7080000 SALESMAN 1606 300000000 SALESMAN 1256 500000000 78
  74. 74. SQL> 2 3 4 5 6 7 8 9 10 11 select ... from ( select empno, ename, job, sal, comm, VERSIONS_XID from EMP versions between timestamp timestamp '2014-02-11 20:12:00' and systimestamp ) e, SYS.SYS_FBA_CONTEXT_AUD a where e.VERSIONS_XID = a.XID; 79
  75. 75. keep an eye on space SYSTEM tablespace 80
  76. 76. 2) 81
  77. 77. total recall is now … 75
  78. 78. free ! 76
  79. 79. let me repeat 77
  80. 80. oracle feature that is free ! 78
  81. 81. basis versus advanced 79
  82. 82. compression choose your cost partitioning 87
  83. 83. so think about total recall 81
  84. 84. secure read only 89
  85. 85. efficient fdba 90
  86. 86. all your history... 84
  87. 87. all your audit... 85
  88. 88. be careful... silent errors 93
  89. 89. 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" 94
  90. 90. Feature: better truncate 88
  91. 91. 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. 89
  92. 92. SQL> truncate table PARENT; truncate table PARENT * ERROR at line 1: ORA-02266: unique/primary keys in table referenced by enabled foreign keys 90
  93. 93. 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); 1 row created. SQL> insert into CHILD values (1,1); 1 row created. SQL> truncate table PARENT; truncate table PARENT * ERROR at line 1: ORA-02266: unique/primary keys in table referenced by enabled foreign keys 91
  94. 94. 12c 92
  95. 95. SQL> truncate table PARENT cascade; Table truncated. 93
  96. 96. must be on delete cascade 94
  97. 97. 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 95
  98. 98. full cascade 96
  99. 99. referential partitions 97
  100. 100. Feature session level sequence 98
  101. 101. SQL> create sequence SESS_SEQ session; Sequence created. 99
  102. 102. SQL> select sess_seq.nextval from dual; NEXTVAL ---------1 SQL> conn scott/tiger Connected. SQL> select sess_seq.nextval from dual; NEXTVAL ---------1 100
  103. 103. "big deal" 101
  104. 104. "bad" reason 102
  105. 105. SQL> select X 2 from GTT; SQL> select X 2 from GTT; X ---------1 2 3 4 5 6 7 8 9 ... X ---------1 2 3 4 5 6 7 8 9 ... 103
  106. 106. better reason 104
  107. 107. contention 105
  108. 108. SQL> create sequence NORMAL cache 1000; Sequence created. SQL> alter session set sql_trace = true; Session altered. SQL> 2 3 4 insert into GTT select SESS_SEQ.NEXTVAL from dual connect by level < 50000; 49999 rows created. SQL> 2 3 4 insert into GTT select NORMAL.NEXTVAL from dual connect by level < 50000; 49999 rows created. 106
  109. 109. insert into GTT select NORMAL.NEXTVAL from dual connect by level < 50000 call count ------- -----Parse 1 Execute 1 Fetch 0 ------- -----total 2 cpu elapsed disk query current -------- ---------- ---------- ---------- ---------0.00 0.00 0 0 0 0.35 0.35 0 147 642 0.00 0.00 0 0 0 -------- ---------- ---------- ---------- ---------0.35 0.35 0 147 642 rows ---------0 49999 0 ---------49999 107
  110. 110. insert into GTT select SESS_SEQ.NEXTVAL from dual connect by level < 50000 call count ------- -----Parse 1 Execute 1 Fetch 0 ------- -----total 2 cpu elapsed disk query current -------- ---------- ---------- ---------- ---------0.00 0.00 0 0 0 0.25 0.25 0 145 592 0.00 0.00 0 0 0 -------- ---------- ---------- ---------- ---------0.25 0.25 0 145 592 rows ---------0 49999 0 ---------49999 108
  111. 111. 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 ------- -----Parse 1 Execute 50 Fetch 0 ------- -----total 51 cpu elapsed disk query current -------- ---------- ---------- ---------- ---------0.00 0.00 0 0 0 0.00 0.00 0 50 103 0.00 0.00 0 0 0 -------- ---------- ---------- ---------- ---------0.00 0.00 0 50 103 rows ---------0 50 0 ---------50 109
  112. 112. Feature defaults 110
  113. 113. the most common ... 111
  114. 114. and the absolute worst ... 112
  115. 115. usage of triggers 113
  116. 116. SQL> create sequence seq; Sequence created. SQL> create table T ( pk number , c1 int); Table created. SQL> 2 3 4 5 6 7 8 create or replace trigger FILL_IN_PK before insert on T for each row begin select seq.nextval into :new.pk from dual; end; / Trigger created. 114
  117. 117. SQL> insert into T values (10,20); 1 row created. SQL> select * from T; PK C1 ---------- ---------1 20 115
  118. 118. we got smarter 116
  119. 119. SQL> 2 3 4 5 6 7 8 9 create or replace trigger FILL_IN_PK before insert on T for each row when ( new.pk is null ) begin select seq.nextval into :new.pk from dual; end; / Trigger created. SQL> insert into T values (20,20); 1 row created. SQL> select * from T; PK C1 ---------- ---------1 20 20 20 117
  120. 120. triggers
  121. 121. over rated ... for that stuff
  122. 122. insert /* with trigger */ into T select rownum, rownum from dual connect by level <= 50000 call count ------- -----Parse 1 Execute 1 Fetch 0 ------- -----total 2 cpu elapsed disk query current -------- ---------- ---------- ---------- ---------0.00 0.00 0 0 0 5.64 5.64 0 466 1608 0.00 0.00 0 0 0 -------- ---------- ---------- ---------- ---------5.64 5.65 0 466 1608 rows ---------0 50000 0 ---------50000
  123. 123. insert /* without trigger */ into T select rownum, rownum from dual connect by level <= 50000 call count ------- -----Parse 1 Execute 1 Fetch 0 ------- -----total 2 cpu elapsed disk query current -------- ---------- ---------- ---------- ---------0.00 0.00 0 0 0 0.09 0.15 0 466 1620 0.00 0.00 0 0 0 -------- ---------- ---------- ---------- ---------0.09 0.15 0 466 1620 rows ---------0 50000 0 ---------50000
  124. 124. 12c ... finally !
  125. 125. SQL> create table T ( pk number default seq.nextval , 2 c1 int); Table created. 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 123
  126. 126. insert /* with default */ into T select rownum, rownum from dual connect by level <= 50000 call count ------- -----Parse 1 Execute 1 Fetch 0 ------- -----total 2 cpu elapsed disk query current -------- ---------- ---------- ---------- ---------0.00 0.00 0 0 0 0.06 0.07 0 467 1608 0.00 0.00 0 0 0 -------- ---------- ---------- ---------- ---------0.06 0.08 0 467 1608 rows ---------0 50000 0 ---------50000
  127. 127. other default improvements
  128. 128. "identity"
  129. 129. 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 ---------414914 414915 OBJECT_NAME -----------------T ISEQ$$_414914 OBJECT_TYPE -----------TABLE SEQUENCE 127
  130. 130. SQL> @pr "select * from user_sequences" SEQUENCE_NAME MIN_VALUE MAX_VALUE INCREMENT_BY CYCLE_FLAG ORDER_FLAG CACHE_SIZE LAST_NUMBER PARTITION_COUNT SESSION_FLAG KEEP_VALUE : : : : : : : : : : : ISEQ$$_414914 1 9999999999999999999999 1 N N 20 1 N N 128
  131. 131. 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 129
  132. 132. more null control
  133. 133. before 12c
  134. 134. 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. 132
  135. 135. SQL> select * from T; PK STATUS ---------- -----1 N 2 N 3 133
  136. 136. workarounds ugly 134
  137. 137. SQL> 2 3 4 5 6 7 8 9 10 11 12 create or replace procedure ins(p_pk int, p_status varchar2) is begin if p_status is null then insert into T (pk, status) values (p_pk, default ); else insert into T (pk, status) values (p_pk, p_status ); end if; end; / Procedure created. 135
  138. 138. 12c "on null"
  139. 139. SQL> create table T ( 2 pk int, 3 status varchar2(1) 4 start_date date 5 6 commission int 7 job_level int 8 ); default on null 'N' , default on null trunc(sysdate,'MM'), default on null 1000, default on null 1 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 137
  140. 140. Feature temporal validity
  141. 141. wtf
  142. 142. very common 140
  143. 143. "when" is a row valid 141
  144. 144. SQL> CREATE TABLE 2 empno 3 name 4 sal 5 deptno 6 start_dt 7 end_dt 8 9 ); emp_temporal ( NUMBER, VARCHAR2(30), NUMBER, NUMBER, DATE, DATE, Table created. 142
  145. 145. 12c part of the definition 143
  146. 146. 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. 144
  147. 147. examples 145
  148. 148. SQL> select * from emp_temporal 2 order by empno, start_dt; EMPNO ---------7369 7369 7499 7499 7521 7521 7566 7566 7654 7654 7698 NAME SAL DEPTNO START_DT END_DT ------------ ---------- ---------- --------- --------SMITH 806 20 01-JAN-14 01-MAR-14 SMITHX 8060 21 02-MAR-14 01-OCT-14 ALLEN 1606 30 01-JAN-14 01-MAR-14 ALLENX 16060 31 02-MAR-14 01-OCT-14 WARD 1256 30 01-JAN-14 01-MAR-14 WARDX 12560 31 02-MAR-14 01-OCT-14 JONES 2981 20 01-JAN-14 01-MAR-14 JONESX 29810 21 02-MAR-14 01-OCT-14 MARTIN 1256 30 01-JAN-14 01-MAR-14 MARTINX 12560 31 02-MAR-14 01-OCT-14 BLAKE 2856 30 01-JAN-14 01-MAR-14 146
  149. 149. SQL> select * from emp_temporal 2 as of period for valid_range '01-FEB-14'; EMPNO ---------7369 7499 7521 7566 7654 NAME SAL DEPTNO START_DT END_DT ------------ ---------- ---------- --------- --------SMITH 806 20 01-JAN-14 01-MAR-14 ALLEN 1606 30 01-JAN-14 01-MAR-14 WARD 1256 30 01-JAN-14 01-MAR-14 JONES 2981 20 01-JAN-14 01-MAR-14 MARTIN 1256 30 01-JAN-14 01-MAR-14 147
  150. 150. so what's happening ? 148
  151. 151. another new feature 149
  152. 152. Feature query expansion 150
  153. 153. 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 151
  154. 154. 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 152
  155. 155. SQL> 2 3 4 5 6 7 8 9 10 11 12 create or replace view MY_VIEW as select o.owner, o.created, s.bytes, s.tablespace_name from dba_segments s, all_objects o where o.owner = s.owner and o.object_name = s.segment_name; View created. 153
  156. 156. 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", 154
  157. 157. "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", 155
  158. 158. "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 156
  159. 159. 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", 157
  160. 160. "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 158
  161. 161. "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 159
  162. 162. "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 160
  163. 163. "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", 161
  164. 164. "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 162
  165. 165. 16 ... more pages 163
  166. 166. back to temporal validity 164
  167. 167. 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 /
  168. 168. 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" 166
  169. 169. existing tables 167
  170. 170. SQL> desc EMPLOYEE Name Null? ------------------------- -------EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO Type --------------NUMBER(4) VARCHAR2(10) VARCHAR2(9) NUMBER(4) DATE NUMBER(7,2) NUMBER(12,2) NUMBER(2) SQL> alter table EMPLOYEE add period for TIME_RANGE; Table altered. 168
  171. 171. SQL> desc EMPLOYEE Name Null? ------------------------- -------EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO Type --------------NUMBER(4) VARCHAR2(10) VARCHAR2(9) NUMBER(4) DATE NUMBER(7,2) NUMBER(12,2) NUMBER(2) still looks the same ? 169
  172. 172. SQL> 2 3 4 select column_name , hidden_column from user_tab_cols where table_name = 'EMPLOYEE' order by column_id; COLUMN_NAME -----------------------------EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO TIME_RANGE_START TIME_RANGE_END TIME_RANGE HIDDEN_COLUMN ------------NO NO NO NO NO NO NO NO YES YES YES 170
  173. 173. multi temporal validity 171
  174. 174. SQL> alter table EMP_TEMPORAL add period for CAL_RANGE; Table altered. SQL> alter table EMP_TEMPORAL add period for FINYR_RANGE; Table altered. 172
  175. 175. maybe a 12.x feature ? 173
  176. 176. no temporal constraints 174
  177. 177. 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 (SYS_C009892) violated 175
  178. 178. add START_DT to primary key ?
  179. 179. no temporal validation 177
  180. 180. 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.
  181. 181. no (native) temporal DML 179
  182. 182. SQL> 2 3 4 update EMP_TEMPORAL as of period for valid_range '01-FEB-14' set sal = 10 where empno = 20; as of period for valid_range '01-FEB-14' * ERROR at line 2: ORA-08187: snapshot expression not allowed here
  183. 183. SQL> update 2 ( select * from EMP_TEMPORAL 3 as of period for valid_range '01-FEB-14' 4 ) 5 set sal = 10 6 where empno = 20; 1 row updated. 181
  184. 184. and one more issue…
  185. 185. "Temporal validity is not supported with a multitenant container database" 183
  186. 186. Feature PL/SQL debugging
  187. 187. it all starts off easy 185
  188. 188. SQL> 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 create or replace procedure P is x int; y int; begin x := 10; select into from where count(*) y all_objects object_name = 'NUFFIN'; x := x / y; select rownum into x from dual; end; / Procedure created. 186
  189. 189. 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 187
  190. 190. SQL> 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 create or replace procedure P is x int; y int; begin x := 10; select into from where count(*) y all_objects object_name = 'NUFFIN'; x := x / y; select rownum into x from dual; end; / Procedure created. 188
  191. 191. ... and downhill from there
  192. 192. SQL> 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 create or replace procedure P is x int; y int; begin x := 10; select into from where count(*) y all_objects object_name = 'NUFFIN'; x := x / y; select rownum into x from dual; exception when others then log_error; raise; end; / 190
  193. 193. SQL> exec P; BEGIN P; END; * ERROR at line 1: ORA-01476: divisor is equal to zero ORA-06512: at "SCOTT.P", line 22
  194. 194. SQL> 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 create or replace procedure P is x int; y int; begin x := 10; select into from where count(*) y all_objects object_name = 'NUFFIN'; ? x := x / y; select rownum into x from dual; exception when others then log_error; raise; end; / 192
  195. 195. SQL> 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 create or replace procedure P is x int; y int; begin x := 10; select into from where count(*) y all_objects object_name = 'NUFFIN'; x := x / y; select rownum into x from dual; exception when others then dbms_output.put_line( dbms_utility.format_call_stack); raise; end; /
  196. 196. 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 194
  197. 197. SQL> 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 create or replace procedure P is x int; y int; l_debug varchar2(4000); begin l_debug := dbms_utility.format_call_stack; x := 10; l_debug := dbms_utility.format_call_stack; select count(*) into y from all_objects where object_name = 'NUFFIN'; l_debug := dbms_utility.format_call_stack; x := x / y; l_debug := dbms_utility.format_call_stack; select rownum into x from dual; exception when others then dbms_output.put_line(l_debug); raise; end;
  198. 198. 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 196
  199. 199. 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 25 26 27 28 29 30 31 exception when others then l_debug := substr(l_debug,instr(l_debug,chr(10),1,3)); l_debug := regexp_replace(l_debug,chr(10)||'.*$'); dbms_output.put_line(l_debug); raise; end; /
  200. 200. SQL> exec P; 0x14b1e3900 BEGIN P; END; 16 procedure SCOTT.P * ERROR at line 1: ORA-01476: divisor is equal to zero ORA-06512: at "SCOTT.P", line 29 ORA-06512: at line 1 198
  201. 201. 10g got better
  202. 202. DBMS_UTILITY.FORMAT_ERROR_BACKTRACE 200
  203. 203. 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;
  204. 204. 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 202
  205. 205. still parsing strings
  206. 206. 12c .... finally 204
  207. 207. UTL_CALL_STACK
  208. 208. 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; 206
  209. 209. 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
  210. 210. value in "real world" 208
  211. 211. SQL> create or replace package PKG is 2 procedure p; 3 procedure p1; 4 procedure p2; 5 procedure p3; 6 end; 7 / Package created.
  212. 212. 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 / 210
  213. 213. 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
  214. 214. did you miss it ? 212
  215. 215. SQL> exec pkg.p3 23-PKG.P 32-PKG.P1 33-PKG.P2 34-PKG.P3 1-__anonymous_block subprogram !!! 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
  216. 216. Feature inline PLSQL in SQL 214
  217. 217. every system ...
  218. 218. ... I've worked on 216
  219. 219. struggles with cAsE
  220. 220. no correlation :-) 218
  221. 221. SQL> select surname 2 from names; SURNAME -----------------------------jones brown SMITH sigh...
  222. 222. "no problem.... I'll use initcap" 220
  223. 223. SQL> select initcap(surname) 2 from names; INITCAP(SURNAME) -----------------------------Jones Brown Smith
  224. 224. until ... 222
  225. 225. SQL> select initcap(surname) 2 from names; INITCAP(SURNAME) -----------------------------Jones Brown Smith Mcdonald Johnson'S uh oh
  226. 226. home grown 224
  227. 227. SQL> 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 create or replace function my_initcap(p_string varchar2) return varchar2 is l_string varchar2(1000) := p_string; begin if regexp_like(l_string,'(Mac[A-Z]|Mc[A-Z])') then null; elsif l_string like '''%' then null; else l_string := initcap(l_string); if l_string like '_''S%' then null; else l_string := replace(l_string,'''S','''s'); end if; end if; return l_string; end; / Function created.
  228. 228. cool ... 226
  229. 229. SQL> select my_initcap(surname) 2 from names; MY_INITCAP(SURNAME) -------------------------Jones Brown Smith McDonald Johnson's
  230. 230. until ... 228
  231. 231. "don't call PLSQL from SQL !!!!" 230
  232. 232. SQL> select max(x) 2 from ( 3 select /*+ no_merge */ initcap(source) x 4 from sys.source$ 5 ); ... Elapsed: 00:00:00.48
  233. 233. SQL> select max(x) 2 from ( 3 select /*+ no_merge */ initcap(source) x 4 from sys.source$ 5 ); ... SQL> select max(x) 2 from ( Elapsed: select /*+ no_merge */ my_initcap(source) x 00:00:00.48 3 4 from sys.source$ 5 ); Elapsed: 00:00:09.37
  234. 234. it can be done in SQL 232
  235. 235. 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
  236. 236. "Always code as if the person who ends up maintaining your code is a psychopathic killer who knows where you live." - source unknown 234
  237. 237. 12c ... user defined functions
  238. 238. 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 O'Brien Johnson's 236
  239. 239. multiple routines
  240. 240. SQL> 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 WITH function is_scottish(p_string varchar2) return boolean is begin return regexp_like(p_string,'(Mac[A-Z]|Mc[A-Z])'); end; function my_initcap(p_string varchar2) return varchar2 is l_string varchar2(1000) := p_string; begin if is_scottish(l_string) then null; elsif l_string like '''%' then null; else l_string := initcap(l_string); if l_string like '_''S%' then null; else l_string := replace(l_string,'''S','''s'); end if; end if; return l_string; end; select my_initcap(surname) from names; / 238
  241. 241. note: 12c client 239
  242. 242. 11.2 and below
  243. 243. 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> 2 3 4 5 6 7 begin if regexp_like(l_string,'(Mac[A-Z]|Mc[A-Z])') then null; elsif l_string like '''%' then null; else l_string := initcap(l_string); 241
  244. 244. workaround SQL> set SQLTERMINATOR ... 242
  245. 245. and a blast from the past :-)
  246. 246. 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. SQL> sho err Errors for PROCEDURE NAMES_PROCESSOR: LINE/COL -------3/7 4/18 22/7 ERROR -----------------------------------------------PL/SQL: SQL Statement ignored PL/SQL: ORA-00905: missing keyword PLS-00103: Encountered the symbol "SELECT" 244
  247. 247. 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.
  248. 248. WITH_PLSQL unrelated to previous 246
  249. 249. DML (or complex SQL)
  250. 250. 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 248
  251. 251. 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.
  252. 252. determinism 250
  253. 253. SQL> 2 3 4 5 6 7 8 9 with function f return timestamp as begin return systimestamp; end; select f from dual connect by level <= 10; / 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 ...
  254. 254. DETERMINISTIC keyword 252
  255. 255. SQL> 2 3 4 5 6 7 8 9 with function f return timestamp DETERMINISTIC as begin return systimestamp; end; select f from dual connect by level <= 10; / 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 ...
  256. 256. conventional scalar caching 254
  257. 257. SQL> 2 3 4 5 6 7 8 9 with function f return timestamp as begin return systimestamp; end; select ( select f from dual ) from dual connect by level <= 10; / 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 ...
  258. 258. are they really faster ? 256
  259. 259. SQL> 2 3 4 5 6 create or replace function F return number is begin return 1; end; / Function created.
  260. 260. SQL> 2 3 4 5 6 7 select sum(f) from ( select level from dual connect by level <= 1000 ), ( select level from dual connect by level <= 1000 ) ; SUM(F) ---------1000000 Elapsed: 00:00:02.04 258
  261. 261. SQL> 2 3 4 5 6 7 8 9 10 11 12 with function f1 return number is begin return 1; end; select sum(f1) from ( select level from dual connect by level <= 1000 ), ( select level from dual connect by level <= 1000 ) / SUM(F1) ---------1000000 Elapsed: 00:00:00.52
  262. 262. "but what about all my PLSQL !!!" 260
  263. 263. SQL> 2 3 4 5 6 7 create or replace function F return number is pragma udf; begin return 1; end; / SQL> 2 3 4 5 6 7 select sum(f) from ( select level from dual connect by level <= 1000 ), ( select level from dual connect by level <= 1000 ) ; SUM(F) ---------1000000 Elapsed: 00:00:00.36
  264. 264. Feature top-n simplifications 262
  265. 265. "5 most recently hired employees" 263
  266. 266. SQL> 2 3 4 select empno, ename, hiredate from emp where rownum <= 5 order by hiredate desc; EMPNO ---------7654 7566 7521 7499 7369 ENAME ---------MARTIN JONES WARD ALLEN SMITH HIREDATE ------------------28/09/1981 00:00:00 02/04/1981 00:00:00 22/02/1981 00:00:00 20/02/1981 00:00:00 17/12/1980 00:00:00 264
  267. 267. SQL> 2 3 4 select empno, ename, hiredate from emp where rownum <= 5 order by hiredate desc; EMPNO ---------7654 7566 7521 7499 7369 ENAME ---------MARTIN JONES WARD ALLEN SMITH HIREDATE ------------------28/09/1981 00:00:00 02/04/1981 00:00:00 22/02/1981 00:00:00 20/02/1981 00:00:00 17/12/1980 00:00:00 264
  268. 268. inline view 265
  269. 269. SQL> 2 3 4 5 6 7 select * from ( select empno, ename, hiredate from emp order by hiredate desc ) where rownum <= 2; EMPNO ---------7876 7788 ENAME ---------ADAMS SCOTT HIREDATE --------23-MAY-87 19-APR-87 266
  270. 270. -----------------------------------------------| 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 | ------------------------------------------------ 267
  271. 271. SQL> 2 3 4 5 6 7 8 select * from ( select empno, ename, hiredate, row_number() over ( order by hiredate desc) rn from emp ) where rn <= 2; 268
  272. 272. ------------------------------------------------| 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) 269
  273. 273. 12c .... "easier" 270
  274. 274. SQL> 2 3 4 select empno, ename, hiredate from emp order by hiredate desc fetch first 2 rows only; EMPNO ---------7876 7788 ENAME ---------ADAMS SCOTT HIREDATE --------23-MAY-87 19-APR-87 271
  275. 275. behind the scenes 272
  276. 276. ------------------------------------------------| 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) 273
  277. 277. variations 274
  278. 278. SQL> 2 3 4 select empno, ename, hiredate from emp order by hiredate desc fetch first 1 row only; EMPNO ENAME HIREDATE ---------- ---------- --------7876 ADAMS 23-MAY-87 275
  279. 279. SQL> 2 3 4 select empno, ename, hiredate from emp order by hiredate desc fetch first 5 row only; EMPNO ---------7876 7788 7934 7900 7902 ENAME ---------ADAMS SCOTT MILLER JAMES FORD HIREDATE --------23-MAY-87 19-APR-87 23-JAN-82 03-DEC-81 03-DEC-81 276
  280. 280. SQL> 2 3 4 select empno, ename, hiredate from emp order by hiredate desc fetch first 10 percent rows only; EMPNO ---------7876 7788 ENAME ---------ADAMS SCOTT HIREDATE --------23-MAY-87 19-APR-87 277
  281. 281. pagination 278
  282. 282. SQL> 2 3 4 select empno, ename, hiredate from emp order by hiredate desc offset 5 rows fetch next 3 rows only; EMPNO ---------7839 7654 7844 ENAME ---------KING MARTIN TURNER HIREDATE --------17-NOV-81 28-SEP-81 08-SEP-81 279
  283. 283. can mimic rownum 280
  284. 284. SQL> select empno, ename, hiredate 2 from emp 4 fetch first 3 rows only; EMPNO ---------7369 7499 7521 ENAME ---------SMITH ALLEN WARD HIREDATE --------17-DEC-80 20-FEB-81 22-FEB-81 281
  285. 285. ----------------------------------------------| Id | Operation | Name | Rows | ----------------------------------------------| 0 | SELECT STATEMENT | | 14 | |* 1 | VIEW | | 14 | |* 2 | WINDOW NOSORT STOPKEY| | 14 | | 3 | TABLE ACCESS FULL | EMP | 14 | ----------------------------------------------1 - filter("from$_subquery$_002"."rowlimit_$ 2 - filter(ROW_NUMBER() OVER ( ORDER BY NULL ) <= 3 282
  286. 286. idiosyncracies 283
  287. 287. SQL> 2 3 4 select empno, ename, hiredate from emp order by hiredate desc fetch LAST 5 rows only; fetch LAST 5 rows only * ERROR at line 4: ORA-00905: missing keyword 284
  288. 288. SQL> 2 3 4 5 6 7 8 select * from ( select empno, ename, hiredate from emp order by hiredate asc fetch first 5 rows only ) order by hiredate desc; EMPNO ---------7698 7566 7521 7499 7369 ENAME ---------BLAKE JONES WARD ALLEN SMITH HIREDATE --------01-MAY-81 02-APR-81 22-FEB-81 20-FEB-81 17-DEC-80 285
  289. 289. or ... 286
  290. 290. SQL> 2 3 4 5 select empno, ename, hiredate from emp order by hiredate desc offset ( select count(*)-5 from emp) rows fetch first 5 rows only; EMPNO ---------7698 7566 7521 7499 7369 ENAME ---------BLAKE JONES WARD ALLEN SMITH HIREDATE --------01-MAY-81 02-APR-81 22-FEB-81 20-FEB-81 17-DEC-80 287
  291. 291. ---------------------------------------------| Id | Operation | Name | Rows | ---------------------------------------------| 0 | SELECT STATEMENT | | 14 | |* 1 | VIEW | | 14 | | 2 | WINDOW SORT | | 14 | | 3 | TABLE ACCESS FULL| EMP | 14 | | 4 | SORT AGGREGATE | | 1 | | 5 | INDEX FULL SCAN | PK_EMP | 14 | ---------------------------------------------- ugh 288
  292. 292. no percent pagination 289
  293. 293. SQL> 2 3 4 5 select empno, ename, hiredate from emp order by hiredate desc offset 20 percent fetch next 10 percent rows only; offset 20 percent fetch next 10 percent rows only * ERROR at line 4: ORA-00905: missing keyword 290
  294. 294. SQL> 2 3 4 5 6 select empno, ename, hiredate from emp order by hiredate desc offset ( select 20/100*count(*) from emp) rows fetch next 10 percent rows only; EMPNO ---------7934 7902 ENAME ---------MILLER FORD HIREDATE --------23-JAN-82 03-DEC-81 291
  295. 295. plsql quirk 292
  296. 296. "Note that in real life, you would use bind variables instead of hard-coded literals" - Tom Kyte, Oracle Magazine, Sep 13 293
  297. 297. "why" in next session 294
  298. 298. SQL> variable x number SQL> exec :x := 5 PL/SQL procedure successfully completed. SQL> 2 3 4 select empno, ename, hiredate from emp order by hiredate desc fetch first :x rows only; EMPNO ---------7876 7788 7934 7900 7902 ENAME ---------ADAMS SCOTT MILLER JAMES FORD HIREDATE --------23-MAY-87 19-APR-87 23-JAN-82 03-DEC-81 03-DEC-81 295
  299. 299. SQL> declare 2 l_num number := 5; 3 begin 4 for i in ( 5 select empno, ename, hiredate 6 from 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 296
  300. 300. SQL> 2 3 4 5 6 7 8 9 10 11 12 13 14 declare l_num number := 5; begin for i in ( select empno, ename, hiredate from emp order by hiredate desc fetch first cast(l_num as number) rows only ) loop null; end loop; end; / PL/SQL procedure successfully completed. 297
  301. 301. Feature join enhancements
  302. 302. 11.2 299
  303. 303. SQL> create table emp2 as 2 select * from emp; Table created. SQL> select * 2 from emp e, 3 emp2 e2, 4 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 300
  304. 304. but ANSI syntax works … 301
  305. 305. 12c 302
  306. 306. SQL> 2 3 4 5 6 7 8 select * from emp e, emp2 e2, dept d where e.deptno = d.deptno(+) and e2.deptno = d.deptno(+) and e.empno = e2.empno / EMPNO ENAME JOB MGR ---------- ---------- --------- ---------7934 MILLER CLERK 7782 ... 303
  307. 307. correlated inline views 304
  308. 308. SQL> drop table DEPT_BENEFITS purge; Table dropped. SQL> create table DEPT_BENEFITS as 2 select d.*, 10 benefits from dept d; Table created. SQL> insert into DEPT_BENEFITS 2 select d.*, 20 benefits from dept d; 4 rows created. 305
  309. 309. SQL> 2 3 4 5 select e.empno, e.deptno, d.benefits from emp e, DEPT_BENEFITS d where e.deptno = d.deptno 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 ... ... 306
  310. 310. "benefits for each employee" 307
  311. 311. SQL> select e.empno, d.deptno, b.benefits 2 from emp e, 3 ( select benefits 4 from 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 308
  312. 312. CROSS APPLY 309
  313. 313. SQL> select e.empno, e.deptno, b.benefits 2 from emp e 3 CROSS APPLY 4 ( select benefits 5 from 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 ... ...
  314. 314. "big deal" 311
  315. 315. SQL> select e.empno, 2 from emp e, 3 ( select 4 from 5 where 6 ) b 7 8 order by 1,3; d.deptno, b.benefits benefits DEPT_BENEFITS d d.deptno = e.deptno 312
  316. 316. SQL> 2 3 4 5 6 7 8 select e.empno, d.deptno, b.benefits from emp e, ( select benefits from DEPT_BENEFITS d ) b where d.deptno = e.deptno order by 1,3; 312
  317. 317. "best benefit for each employee" 313
  318. 318. SQL> select e.empno, e.deptno, b.benefits 2 from emp e 3 CROSS APPLY 4 ( select benefits 5 from 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 ... 314
  319. 319. Feature adaptive plans 315
  320. 320. 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> 2 3 4 insert into PARENT select rownum*2+1, rownum from dual connect by level <= 500; 500 rows created. SQL> 2 3 4 insert into CHILD select rownum, mod(rownum,1000)*2, rownum from dual connect by level < 10000; 9999 rows created. 316
  321. 321. 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 317
  322. 322. SQL> set autotrace traceonly explain SQL> 2 3 4 5 select * from PARENT p, CHILD c where p.p < 10 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 318
  323. 323. now lets mess with it 319
  324. 324. SQL> 2 3 4 insert into PARENT select mod(rownum,5)*2+1, rownum from dual connect by level <= 20000; 20000 rows created. SQL> commit; Commit complete. SQL> select count(*) from PARENT 2 where p < 10; COUNT(*) ---------20004 320
  325. 325. a new cursor 321
  326. 326. SQL> 2 3 4 5 select /*+ gather_plan_statistics */ * from CHILD c, PARENT p where p.p < 10 and p.p = c.p; no rows selected SQL> select * 2 from table( 3 dbms_xplan.display_cursor( 4 null,null,'ALLSTATS LAST +ADAPTIVE')); 322
  327. 327. ----------------------------------------------------------| 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 | -----------------------------------------------------------
  328. 328. ----------------------------------------------------------| 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 | -----------------------------------------------------------
  329. 329. ----------------------------------------------------------| 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 | -----------------------------------------------------------
  330. 330. ----------------------------------------------------------| 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 | -----------------------------------------------------------
  331. 331. 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 327
  332. 332. just be aware 328
  333. 333. tools will (hopefully) catch up 329
  334. 334. Feature invisible columns 330
  335. 335. have been there "forever" 331
  336. 336. function based indexes 332
  337. 337. set column unused 333
  338. 338. 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. 334
  339. 339. SQL> 2 3 4 select from where order column_name, data_default USER_TAB_COLS table_name = 'T' by column_id; COLUMN_NAME DATA_DEFAULT ------------------------------ ---------------X SYS_NC00003$ "X"+0 SYS_C00002_14020720:50:28$ 335
  340. 340. now exposed to us 336
  341. 341. SQL> create table T ( c1 int, c2 int, c3 int ); SQL> desc T Name Null? ---------------------------- -------C1 C2 C3 Type ------NUMBER(38) NUMBER(38) NUMBER(38) SQL> alter table T modify c1 invisible; SQL> desc T Name Null? ---------------------------- -------C2 C3 Type ------NUMBER(38) NUMBER(38) 337
  342. 342. and an idiosyncracy... 338
  343. 343. SQL> alter table T modify c1 visible; SQL> desc T Name Null? ---------------------------- -------C2 C3 C1 Type ------NUMBER(38) NUMBER(38) NUMBER(38) 339
  344. 344. requires discipline 340
  345. 345. SQL> 2 3 4 5 6 7 create or replace procedure P is begin insert into T (c1,c2,c3) values (1,10,100); end; / 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. 341
  346. 346. 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? ------------------- -------C2 C3 C1 Type -------------------NUMBER(38) NUMBER(38) NUMBER(38) 342
  347. 347. SQL> 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 create or replace procedure FIX_COLS(p_tab varchar2, p_col_list varchar2) is l_col_list varchar2(1000) := p_col_list||','; type clist is table of varchar2(30) index by pls_integer; c clist; l_col varchar2(30); l_id int; begin while instr(l_col_list,',') > 1 loop c(c.count+1) := substr(l_col_list,1,instr(l_col_list,',')-1); l_col_list := substr(l_col_list,instr(l_col_list,',')+1); dbms_output.put_line(c(c.count)); end loop; for i in 1 .. c.count loop loop select column_name into l_col from user_tab_columns where table_name = p_tab and column_id = i; exit when l_col = c(i); execute immediate 'alter table '||p_tab||' modify '||l_col||' invisible'; execute immediate 'alter table '||p_tab||' modify '||l_col||' visible'; end loop; end loop; end; / 343
  348. 348. SQL> exec FIX_COLS('T','C1,C2,C3'); PL/SQL procedure successfully completed. SQL> desc T Name Null? ---------------------------- -------C1 C2 C3 Type ------NUMBER(38) NUMBER(38) NUMBER(38) 344
  349. 349. so what's the appeal ? 345
  350. 350. rollout changes online 346
  351. 351. SQL> create table T ( c1 int, c2 int ) ; Table created. SQL> 2 3 4 5 6 7 8 9 create or replace procedure APP1 is begin insert into T select object_id, data_object_id from all_objects where rownum < 10; end; / Procedure created. SQL> exec APP1; PL/SQL procedure successfully completed. 347
  352. 352. new application 348
  353. 353. SQL> alter table T add c3 int; Table altered. SQL> 2 3 4 5 6 7 8 9 10 11 create or replace procedure APP2 is begin for i in ( select c1,c2,c3 from T ) loop dbms_output.put_line(i.c1); dbms_output.put_line(i.c2); dbms_output.put_line(i.c3); end loop; end; / Procedure created. 349
  354. 354. SQL> exec APP2; 28 28 15 15 29 29 25 25 54 PL/SQL procedure successfully completed. 350
  355. 355. 351
  356. 356. 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 353
  357. 357. SQL> alter table T modify c3 invisible; Table altered. SQL> exec APP2; 28 28 15 15 29 29 25 25 54 PL/SQL procedure successfully completed. SQL> exec APP1; PL/SQL procedure successfully completed. 354
  358. 358. tools 355
  359. 359. 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? ------------------------- -------C1 C2 (INVISIBLE) Type ----------NUMBER(38) NUMBER(38) 356
  360. 360. 357
  361. 361. SQL> alter table T add "C3 (INVISIBLE)" int; Table altered. 358
  362. 362. SQL> alter table T add "C3 (INVISIBLE)" int; Table altered. SQL> desc T Name Null? ------------------------- -------C1 C3 (INVISIBLE) C2 (INVISIBLE) Type -----------NUMBER(38) NUMBER(38) NUMBER(38) 358
  363. 363. and a whole lot more features we didnt get to today ... 359
  364. 364. wrap up 396
  365. 365. there's a lot in 12c 397
  366. 366. lots not covered today 398
  367. 367. 399

×