SlideShare a Scribd company logo
1 of 69
Effective PL/SQL Thomas Kyte http://asktom.oracle.com/
Agenda ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Why  PL/SQL
Why Use PL/SQL ,[object Object],[object Object],[object Object],[object Object]
It is the most efficient language for data manipulation ,[object Object]
It is the most efficient language for data manipulation ,[object Object],[object Object],[object Object],[object Object],Create or replace procedure  process_data( p_inputs in varchar2 ) As Begin   For x in ( select * from emp  where ename like p_inputs )   Loop   Process( X );   End loop End;
It is the most efficient language for data manipulation static PreparedStatement  pstmt = null; public static void  process_data ( Connection conn, String inputs ) throws Exception { int  empno; String ename; String job; int  mgr; String hiredate; int  sal; int  comm; int  deptno; if ( pstmt == null ) pstmt = conn.prepareStatement ("select * from emp " + "where ename like ? " ); pstmt.setString( 1, inputs ); ResultSet rset =  pstmt.executeQuery(); …… while( rset.next() ) { empno  = rset.getInt(1); ename  = rset.getString(2); job  = rset.getString(3); mgr  = rset.getInt(4); hiredate = rset.getString(5); sal  = rset.getInt(6); comm  = rset.getInt(7); deptno  = rset.getInt(8); process( empno, ename, job, mgr,  hiredate, sal, comm, deptno ); } rset.close(); } ,[object Object],[object Object],[object Object],[object Object]
PL/SQL epitomizes portability and reusability ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Many mistakes made in other languages using the database are avoided ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
However ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Write as  Little as you can
Code… ,[object Object],[object Object],[object Object],[object Object],[object Object],Begin   For x in ( select * from table@remote_db )   Loop   Insert into table ( c1, c2, … )  values ( x.c1, x.c2,… );   End loop; End;  Insert into table (c1,c2,…)  select c1,c2,…. From table@remote_db Insert into table (c1,c2,…)  select c1,c2,…. From table@remote_db LOG ERRORS (  some_variable  )  REJECT LIMIT UNLIMITED; …  code to handle errors  for tag some_variable …
Use PL/SQL constructs only when SQL cannot do it ,[object Object],[object Object],For a in ( select * from t1 ) Loop For b in ( select * from t2  where t2.key = t1.key ) Loop For c in ( select * from t3  where t3.key = t2.key ) Loop …
More Code = More Bugs Less Code = Less Bugs ,[object Object],[object Object],[object Object],[object Object]
insert into t ( .... ) select EMPNO, STATUS_DATE, ....  from t1, t2, t3, t4, .... where ....; loop delete from t where (EMPNO,STATUS_DATE)  in ( select EMPNO,  min(STATUS_DATE)  from t group by EMPNO having count(1) > 1 ); exit when sql%rowcount = 0; end loop; For any set of records with more than one EMPNO, remove rows with the oldest STATUS_DATE. Additionally – If the last set of EMPNO records all have the same STATUS_DATE, remove them all. More Code = More Bugs Less Code = Less Bugs EMPNO  STATUS_DATE -------  ------------ 1  01-jan-2009 1  15-jun-2009 1  01-sep-2009 … 1000  01-feb-2009 1000  22-aug-2009 1000  10-oct-2009 1000  10-oct-2009 EMPNO  STATUS_DATE -------  ------------ 1  01-sep-2009 … (1,01-jan-2009,3)  (1001,01-feb-2009,4) EMPNO  STATUS_DATE -------  ------------ 1  01-jan-2009 1  15-jun-2009 1  01-sep-2009 … 1000  01-feb-2009 1000  22-aug-2009 1000  10-oct-2009 1000  10-oct-2009 EMPNO  STATUS_DATE -------  ------------ 1  01-jan-2009 1  15-jun-2009 1  01-sep-2009 … 1000  01-feb-2009 1000  22-aug-2009 1000  10-oct-2009 1000  10-oct-2009 (1,15-jun-2009,2)  (1001,22-aug-2009,3) EMPNO  STATUS_DATE -------  ------------ 1  01-jan-2009 1  15-jun-2009 1  01-sep-2009 … 1000  01-feb-2009 1000  22-aug-2009 1000  10-oct-2009 1000  10-oct-2009 (1001,22-aug-2009,2)
insert /* APPEND */ into t ( .... ) select EMPNO, STATUS_DATE, ...... from ( select EMPNO, STATUS_DATE, .... ,  max(STATUS_DATE)  OVER ( partition by EMPNO ) max_sd, count(EMPNO)  OVER ( partition by EMPNO,STATUS_DATE ) cnt from t1, t2, t3, t4, … where … ) where STATUS_DATE = max_sd and cnt = 1; More Code = More Bugs Less Code = Less Bugs ,[object Object],[object Object]
/*  Load table t using history tables.  History tables have multiple records per employee.  We need to keep the history records for each employee that have the maximum status date for that employee.  We do that by computing the max(status_date) for each employee (partition by EMPNO finding max(status_date) and keeping only the records such that the status_date for that record = max(status_date) for all records with same empno  */ insert /* APPEND */ into t ( .... ) select EMPNO, STATUS_DATE, ...... from ( select EMPNO, STATUS_DATE, .... ,  max(STATUS_DATE)  OVER ( partition by EMPNO ) max_sd from t1, t2, t3, t4, … where … ) where STATUS_DATE = max_sd; More Code = More Bugs Less Code = Less Bugs
/*  Load table t using history tables.  History tables have multiple records per employee.  We need to keep the history records for each employee that have the maximum status date for that employee.  We do that by numbering each history record by empno, keeping only the records such that it is the first record for a EMPNO after sorting by  status_date desc.  REALIZE: this is not deterministic if there are two status_dates that are the same for a given  employee!  */ insert /* APPEND */ into t ( .... ) select EMPNO, STATUS_DATE, ...... from ( select EMPNO, STATUS_DATE, .... ,  row_number() OVER ( partition by EMPNO  order by STATUS_DATE desc ) rn from t1, t2, t3, t4, … where … ) where rn=1; More Code = More Bugs Less Code = Less Bugs
[object Object]
Use  Packages
They break the dependency chain ,[object Object],ops$tkyte%ORA10GR2> create or replace procedure p1 as begin null; end; ops$tkyte%ORA10GR2> create or replace procedure p2 as begin p1; end; OBJECT_NAME  STATUS  TO_CHAR(LAST_DD ------------------------------ ------- --------------- P1  VALID  04-oct 12:15:54 P2  VALID  04-oct 12:15:54 ops$tkyte%ORA10GR2> create or replace procedure p1 as begin /* updated */ null; end; OBJECT_NAME  STATUS  TO_CHAR(LAST_DD ------------------------------ ------- --------------- P1  VALID  04-oct 12:15:58 P2  INVALID 04-oct 12:15:54
They increase your namespace ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
They support overloading ,[object Object],[object Object],[object Object],[object Object],[object Object]
They support encapsulation ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Use  Static SQL
Static SQL is checked at compile time ,[object Object],[object Object],[object Object],[object Object]
PL/SQL understands the dictionary ,[object Object],[object Object],[object Object]
One word - dependencies ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Static SQL makes parse once, execute many a reality ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Dynamic SQL – when to use then? ,[object Object],[object Object]
Bulk  Up
Bulk Processing Defined: ,[object Object],[object Object],[object Object],[object Object],[object Object]
Bulk Processing ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Bulk Processing For x in ( select * from t where … ) Loop process(x); update t set … where …; End loop; For x in (select * from t where …) Loop dbms_output.put_line( … t.x … ); End loop; ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Bulk Processing create or replace procedure bulk as type ridArray is table of rowid; type onameArray is table  of t.object_name%type; cursor c is select rowid rid, object_name  from t t_bulk; l_rids  ridArray; l_onames  onameArray; N  number := 100; begin open c; loop fetch c bulk collect  into l_rids, l_onames limit N; for i in 1 .. l_rids.count loop l_onames(i) := substr(l_onames(i),2) ||substr(l_onames(i),1,1); end loop; forall i in 1 .. l_rids.count update t  set object_name = l_onames(i)  where rowid = l_rids(i); exit when c%notfound; end loop; close c; end; create or replace procedure slow_by_slow as begin for x in (select rowid rid, object_name  from t t_slow_by_slow) loop x.object_name := substr(x.object_name,2) ||substr(x.object_name,1,1); update t  set object_name = x.object_name  where rowid = x.rid; end loop; end;
Bulk Processing SELECT ROWID RID, OBJECT_NAME FROM T T_BULK call  count  cpu  elapsed  disk  query  current  rows ------- ------  -------- ---------- ---------- ---------- ----------  ---------- total  721  0.17  0.17  0  22582  0  71825 ******************************************************************************** UPDATE T SET OBJECT_NAME = :B1 WHERE ROWID = :B2 call  count  cpu  elapsed  disk  query  current  rows ------- ------  -------- ---------- ---------- ---------- ----------  ---------- Parse  1  0.00  0.00  0  0  0  0 Execute  719   12.83   13.77  0  71853  74185  71825 Fetch  0  0.00  0.00  0  0  0  0 ------- ------  -------- ---------- ---------- ---------- ----------  ---------- total  720  12.83  13.77  0  71853  74185  71825 SELECT ROWID RID, OBJECT_NAME FROM T T_SLOW_BY_SLOW call  count  cpu  elapsed  disk  query  current  rows ------- ------  -------- ---------- ---------- ---------- ----------  ---------- total  721  0.17  0.17  0  22582  0  71825 ******************************************************************************** UPDATE T SET OBJECT_NAME = :B2 WHERE ROWID = :B1 call  count  cpu  elapsed  disk  query  current  rows ------- ------  -------- ---------- ---------- ---------- ----------  ---------- Parse  1  0.00  0.00  0  0  0  0 Execute  71824   21.25   22.25  0  71836  73950  71824 Fetch  0  0.00  0.00  0  0  0  0 ------- ------  -------- ---------- ---------- ---------- ----------  ---------- total  71825  21.25  22.25  0  71836  73950  71824
But of course, the bulkier the better… SELECT ROWID RID, OBJECT_NAME FROM T T_BULK call  count  cpu  elapsed  disk  query  current  rows ------- ------  -------- ---------- ---------- ---------- ----------  ---------- total  721  0.17  0.17  0  22582  0  71825 ******************************************************************************** UPDATE T SET OBJECT_NAME = :B1 WHERE ROWID = :B2 call  count  cpu  elapsed  disk  query  current  rows ------- ------  -------- ---------- ---------- ---------- ----------  ---------- Parse  1  0.00  0.00  0  0  0  0 Execute  719   12.83   13.77  0  71853  74185  71825 Fetch  0  0.00  0.00  0  0  0  0 ------- ------  -------- ---------- ---------- ---------- ----------  ---------- total  720  12.83  13.77  0  71853  74185  71825 update t set object_name = substr(object_name,2) || substr(object_name,1,1) call  count  cpu  elapsed  disk  query  current  rows ------- ------  -------- ---------- ---------- ---------- ----------  ---------- Parse  1  0.00  0.00  0  0  0  0 Execute  1  1.30   1.44  0  2166  75736  71825 Fetch  0  0.00  0.00  0  0  0  0 ------- ------  -------- ---------- ---------- ---------- ----------  ---------- total  2  1.30  1.44  0  2166  75736  71825 Lots less code too! (dml error logging if you need)
Returning  Data
To return data to a client program  ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Using  Invokers Rights
Invokers versus Definers Rights ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Invokers Rights ops$tkyte%ORA11GR2> create table t 2  as 3  select 'hello world' text 4  from dual 5  / Table created. ops$tkyte%ORA11GR2> create or replace procedure IR 2  as 3  begin 4  for x in ( select * from t) 5  loop 6  dbms_output.put_line(x.text); 7  end loop; 8  end; 9  / Procedure created. ops$tkyte%ORA11GR2> grant all on ops$tkyte.ir to public; Grant succeeded. ops$tkyte%ORA11GR2> create or replace procedure DR 2  AUTHID CURRENT_USER 3  as 4  begin 5  for x in ( select * from t) 6  loop 7  dbms_output.put_line(x.text); 8  end loop; 9  end; 10  / Procedure created. ops$tkyte%ORA11GR2> grant all on ops$tkyte.dr to public; Grant succeeded.
ops$tkyte%ORA11GR2> connect scott/tiger Connected. scott%ORA11GR2> exec ops$tkyte.ir hello world PL/SQL procedure successfully completed. scott%ORA11GR2> exec ops$tkyte.dr BEGIN ops$tkyte.dr; END; * ERROR at line 1: ORA-00942: table or view does not exist ORA-06512: at "OPS$TKYTE.DR", line 5 ORA-06512: at line 1 scott%ORA11GR2> connect / Connected. ops$tkyte%ORA11GR2> grant select on t to scott; Grant succeeded. ops$tkyte%ORA11GR2> connect scott/tiger Connected. scott%ORA11GR2> exec ops$tkyte.dr BEGIN ops$tkyte.dr; END; * ERROR at line 1: ORA-00942: table or view does not exist ORA-06512: at "OPS$TKYTE.DR", line 5 ORA-06512: at line 1 Invokers Rights
scott%ORA11GR2> connect / Connected. ops$tkyte%ORA11GR2> create or replace procedure dr 2  AUTHID CURRENT_USER 3  as 4  begin 5  for x in ( select * from OPS$TKYTE.t) 6  loop 7  dbms_output.put_line(x.text); 8  end loop; 9  end; 10  / Procedure created. ops$tkyte%ORA11GR2> connect scott/tiger Connected. scott%ORA11GR2> exec ops$tkyte.dr hello world PL/SQL procedure successfully completed. scott%ORA11GR2> connect / Connected. ops$tkyte%ORA11GR2> revoke select on t from scott; Revoke succeeded. ops$tkyte%ORA11GR2> connect scott/tiger Connected. scott%ORA11GR2>  exec ops$tkyte.dr BEGIN ops$tkyte.dr; END; * ERROR at line 1: ORA-00942: table or view does not exist ORA-06512: at "OPS$TKYTE.DR", line 5 ORA-06512: at line 1 Invokers Rights
So, which on should we use? ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
So, which on should we use? ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Implicit  versus Explicit
Implicit versus Explicit ,[object Object],[object Object],[object Object],[object Object],For x in ( select * from t where … ) Loop … End loop; Declare cursor c is select * from t where …; l_rec  c%rowtype; Open c; Loop fetch c into l_rec; exit when c%notfound; … End loop; Close c;
Implicit versus Explicit ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Single Row Processing ,[object Object],[object Object],[object Object],Select … INTO <plsql variables> from … where …; Declare cursor c is select … from … where …; Begin open c; fetch c into <plsql variables>; if (c%notfound) then raise no_data_found; end if; fetch c into <plsql variables>; if (c%found) then raise too_many_rows; end if; close c;
Single Row Processing ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],Function get_something return … is cursor c is select … from … where …; Begin open c; fetch c into <plsql variables>; close c; return plsql variables ---------------------------------------- Begin open c1; loop fetch c1 into l_data; exit when c1%notfound; open c2( l_data ); fetch c2 into l_something_else; close c2; process( l_data, l_something_else); end loop; close c1;
Multi-Row Processing ,[object Object],[object Object],[object Object],[object Object],create or replace procedure implicit as begin for x in ( select * from dept ) loop null; end loop; end; ---------------------------------------- create or replace procedure explicit as l_rec  dept%rowtype; cursor c is select * from dept; begin open c; loop fetch c into l_rec; exit when c%notfound; end loop; close c; end;
Multi-Row Processing ,[object Object],[object Object],create or replace procedure implicit As cursor c is select * from dept; begin for x in  C loop null; end loop; end; ---------------------------------------- create or replace procedure explicit as type array is table of dept%rowtype; l_rec  array; n  number := 2; cursor c is select * from dept; begin open c; loop fetch c bulk collect into l_rec limit N; for i in 1 .. l_rec.count loop null; end loop; exit when c%notfound; end loop; close c; end;
Multi-Row Processing ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],create or replace procedure bulk as type ridArray is table of rowid; type onameArray is table of t.object_name%type; cursor c is select rowid rid, object_name  from t t_bulk; l_rids  ridArray; l_onames  onameArray; N  number := 100; begin open c; loop fetch c bulk collect  into l_rids, l_onames limit N; for i in 1 .. l_rids.count loop l_onames(i) := substr(l_onames(i),2) ||substr(l_onames(i),1,1); end loop; forall i in 1 .. l_rids.count update t  set object_name = l_onames(i)  where rowid = l_rids(i); exit when c%notfound; end loop; close c; end;
Beware  of…
Beware – When others ,[object Object],[object Object],[object Object]
When others then null; ,[object Object],[object Object],[object Object],Begin … Exception When others Then log_error( …); End;
When others then null; ops$tkyte%ORA11GR2> create table t( x varchar2(4000) ); Table created. ops$tkyte%ORA11GR2> create or replace 2  procedure maintain_t 3  ( p_str in varchar2 ) 4  as 5  begin 6  insert into t (x) values ( 'hello' ); 7  insert into t (x) values ( p_str ); 8  insert into t (x) values ( 'world' ); 9  exception 10  when others 11  then 12  -- call some log_error() routine 13  null; 14  end; 15  / Procedure created. ops$tkyte%ORA11GR2> exec maintain_t( rpad( 'x', 4001, 'x' ) ); PL/SQL procedure successfully completed. ops$tkyte%ORA11GR2> select * from t; X -------------------- hello 1 row selected.
When others then null; ops$tkyte%ORA11GR2> alter procedure maintain_t compile 2  PLSQL_Warnings = 'enable:all' 3  reuse settings 4  / SP2-0805: Procedure altered with compilation warnings ops$tkyte%ORA11GR2> show errors procedure maintain_t Errors for PROCEDURE MAINTAIN_T: LINE/COL ERROR -------- ----------------------------------------------------------------- 1/1  PLW-05018: unit MAINTAIN_T omitted optional AUTHID clause; default value DEFINER used 9/8  PLW-06009: procedure &quot;MAINTAIN_T&quot; OTHERS handler does not end in RAISE or RAISE_APPLICATION_ERROR
When others then null; ops$tkyte%ORA11GR2> alter procedure maintain_t compile 2  PLSQL_Warnings = 'enable:all' 3  reuse settings 4  / SP2-0805: Procedure altered with compilation warnings ops$tkyte%ORA11GR2> show errors procedure maintain_t Errors for PROCEDURE MAINTAIN_T: LINE/COL ERROR -------- ----------------------------------------------------------------- 1/1  PLW-05018: unit MAINTAIN_T omitted optional AUTHID clause; default value DEFINER used 9/8  PLW-06009:  You have a bug in your code.  Repeat: You have a BUG IN  YOUR CODE.   Procedure &quot;MAINTAIN_T&quot; OTHERS handler does not end in RAISE or RAISE_APPLICATION_ERROR.  Fix it right now. ,[object Object]
When others then null; ops$tkyte%ORA11GR2> create table t( x varchar2(4000) ); Table created. ops$tkyte%ORA11GR2> create or replace 2  procedure maintain_t 3  ( p_str in varchar2 ) 4  as 5  begin 6  insert into t (x) values ( 'hello' ); 7  insert into t (x) values ( p_str ); 8  insert into t (x) values ( 'world' ); 9  exception 10  when others 11  then 12  -- call some log_error() routine 13  RAISE; 14  end; 15  / Procedure created. ops$tkyte%ORA11GR2> exec maintain_t( rpad( 'x', 4001, 'x' ) ); BEGIN maintain_t( rpad( 'x', 4001, 'x' ) ); END; * ERROR at line 1: ORA-01461: can bind a LONG value only for insert into a LONG column ORA-06512: at &quot;OPS$TKYTE.MAINTAIN_T&quot;, line 12 ORA-06512: at line 1 ops$tkyte%ORA11GR2> select * from t; no rows selected
Beware – Autonomous Transactions ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Beware – Triggers ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Things  to do…
[object Object]
[object Object]
[object Object]
[object Object]
 

More Related Content

What's hot

Bioinformatics p4-io v2013-wim_vancriekinge
Bioinformatics p4-io v2013-wim_vancriekingeBioinformatics p4-io v2013-wim_vancriekinge
Bioinformatics p4-io v2013-wim_vancriekingeProf. Wim Van Criekinge
 
Erlang Message Passing Concurrency, For The Win
Erlang  Message  Passing  Concurrency,  For  The  WinErlang  Message  Passing  Concurrency,  For  The  Win
Erlang Message Passing Concurrency, For The Winl xf
 
.Net Multithreading and Parallelization
.Net Multithreading and Parallelization.Net Multithreading and Parallelization
.Net Multithreading and ParallelizationDmitri Nesteruk
 
Comparing different concurrency models on the JVM
Comparing different concurrency models on the JVMComparing different concurrency models on the JVM
Comparing different concurrency models on the JVMMario Fusco
 
More on Lex
More on LexMore on Lex
More on LexTech_MX
 
Valgrind tutorial
Valgrind tutorialValgrind tutorial
Valgrind tutorialSatabdi Das
 
Planet of the AOPs
Planet of the AOPsPlanet of the AOPs
Planet of the AOPsJames Ward
 
Compiler Construction | Lecture 2 | Declarative Syntax Definition
Compiler Construction | Lecture 2 | Declarative Syntax DefinitionCompiler Construction | Lecture 2 | Declarative Syntax Definition
Compiler Construction | Lecture 2 | Declarative Syntax DefinitionEelco Visser
 
Asterisk: PVS-Studio Takes Up Telephony
Asterisk: PVS-Studio Takes Up TelephonyAsterisk: PVS-Studio Takes Up Telephony
Asterisk: PVS-Studio Takes Up TelephonyAndrey Karpov
 

What's hot (20)

PLSQL Tutorial
PLSQL TutorialPLSQL Tutorial
PLSQL Tutorial
 
Plsql
PlsqlPlsql
Plsql
 
Bioinformatics p4-io v2013-wim_vancriekinge
Bioinformatics p4-io v2013-wim_vancriekingeBioinformatics p4-io v2013-wim_vancriekinge
Bioinformatics p4-io v2013-wim_vancriekinge
 
Closures
ClosuresClosures
Closures
 
Breakpoints
BreakpointsBreakpoints
Breakpoints
 
SQL / PL
SQL / PLSQL / PL
SQL / PL
 
Erlang Message Passing Concurrency, For The Win
Erlang  Message  Passing  Concurrency,  For  The  WinErlang  Message  Passing  Concurrency,  For  The  Win
Erlang Message Passing Concurrency, For The Win
 
.Net Multithreading and Parallelization
.Net Multithreading and Parallelization.Net Multithreading and Parallelization
.Net Multithreading and Parallelization
 
Comparing different concurrency models on the JVM
Comparing different concurrency models on the JVMComparing different concurrency models on the JVM
Comparing different concurrency models on the JVM
 
More on Lex
More on LexMore on Lex
More on Lex
 
Functions in c
Functions in cFunctions in c
Functions in c
 
Valgrind tutorial
Valgrind tutorialValgrind tutorial
Valgrind tutorial
 
Planet of the AOPs
Planet of the AOPsPlanet of the AOPs
Planet of the AOPs
 
Compiler Construction | Lecture 2 | Declarative Syntax Definition
Compiler Construction | Lecture 2 | Declarative Syntax DefinitionCompiler Construction | Lecture 2 | Declarative Syntax Definition
Compiler Construction | Lecture 2 | Declarative Syntax Definition
 
Erlang
ErlangErlang
Erlang
 
Perl Intro 4 Debugger
Perl Intro 4 DebuggerPerl Intro 4 Debugger
Perl Intro 4 Debugger
 
Assembler
AssemblerAssembler
Assembler
 
Asterisk: PVS-Studio Takes Up Telephony
Asterisk: PVS-Studio Takes Up TelephonyAsterisk: PVS-Studio Takes Up Telephony
Asterisk: PVS-Studio Takes Up Telephony
 
4. plsql
4. plsql4. plsql
4. plsql
 
PLSQL tutorial...
PLSQL tutorial...PLSQL tutorial...
PLSQL tutorial...
 

Viewers also liked

Date rangestech15
Date rangestech15Date rangestech15
Date rangestech15stewashton
 
SQL for pattern matching (Oracle 12c)
SQL for pattern matching (Oracle 12c)SQL for pattern matching (Oracle 12c)
SQL for pattern matching (Oracle 12c)Logan Palanisamy
 
The Amazing and Elegant PL/SQL Function Result Cache
The Amazing and Elegant PL/SQL Function Result CacheThe Amazing and Elegant PL/SQL Function Result Cache
The Amazing and Elegant PL/SQL Function Result CacheSteven Feuerstein
 
Row Pattern Matching 12c MATCH_RECOGNIZE OOW14
Row Pattern Matching 12c MATCH_RECOGNIZE OOW14Row Pattern Matching 12c MATCH_RECOGNIZE OOW14
Row Pattern Matching 12c MATCH_RECOGNIZE OOW14stewashton
 
Impact Analysis with PL/Scope
Impact Analysis with PL/ScopeImpact Analysis with PL/Scope
Impact Analysis with PL/ScopeSteven Feuerstein
 
All About PL/SQL Collections
All About PL/SQL CollectionsAll About PL/SQL Collections
All About PL/SQL CollectionsSteven Feuerstein
 
Managing SQL Performance
Managing SQL PerformanceManaging SQL Performance
Managing SQL PerformanceKaren Morton
 
Performance Instrumentation for PL/SQL: When, Why, How
Performance Instrumentation for PL/SQL: When, Why, HowPerformance Instrumentation for PL/SQL: When, Why, How
Performance Instrumentation for PL/SQL: When, Why, HowKaren Morton
 

Viewers also liked (8)

Date rangestech15
Date rangestech15Date rangestech15
Date rangestech15
 
SQL for pattern matching (Oracle 12c)
SQL for pattern matching (Oracle 12c)SQL for pattern matching (Oracle 12c)
SQL for pattern matching (Oracle 12c)
 
The Amazing and Elegant PL/SQL Function Result Cache
The Amazing and Elegant PL/SQL Function Result CacheThe Amazing and Elegant PL/SQL Function Result Cache
The Amazing and Elegant PL/SQL Function Result Cache
 
Row Pattern Matching 12c MATCH_RECOGNIZE OOW14
Row Pattern Matching 12c MATCH_RECOGNIZE OOW14Row Pattern Matching 12c MATCH_RECOGNIZE OOW14
Row Pattern Matching 12c MATCH_RECOGNIZE OOW14
 
Impact Analysis with PL/Scope
Impact Analysis with PL/ScopeImpact Analysis with PL/Scope
Impact Analysis with PL/Scope
 
All About PL/SQL Collections
All About PL/SQL CollectionsAll About PL/SQL Collections
All About PL/SQL Collections
 
Managing SQL Performance
Managing SQL PerformanceManaging SQL Performance
Managing SQL Performance
 
Performance Instrumentation for PL/SQL: When, Why, How
Performance Instrumentation for PL/SQL: When, Why, HowPerformance Instrumentation for PL/SQL: When, Why, How
Performance Instrumentation for PL/SQL: When, Why, How
 

Similar to Eff Plsql

Database & Technology 1 _ Tom Kyte _ Efficient PL SQL - Why and How to Use.pdf
Database & Technology 1 _ Tom Kyte _ Efficient PL SQL - Why and How to Use.pdfDatabase & Technology 1 _ Tom Kyte _ Efficient PL SQL - Why and How to Use.pdf
Database & Technology 1 _ Tom Kyte _ Efficient PL SQL - Why and How to Use.pdfInSync2011
 
How to tune a query - ODTUG 2012
How to tune a query - ODTUG 2012How to tune a query - ODTUG 2012
How to tune a query - ODTUG 2012Connor McDonald
 
TAUS USER CONFERENCE 2009, Normalization of translation memories
TAUS USER CONFERENCE 2009, Normalization of translation memoriesTAUS USER CONFERENCE 2009, Normalization of translation memories
TAUS USER CONFERENCE 2009, Normalization of translation memoriesTAUS - The Language Data Network
 
PLSQLmy Updated (1).pptx
PLSQLmy Updated (1).pptxPLSQLmy Updated (1).pptx
PLSQLmy Updated (1).pptxvamsiyadav39
 
PostgreSQL 8.4 TriLUG 2009-11-12
PostgreSQL 8.4 TriLUG 2009-11-12PostgreSQL 8.4 TriLUG 2009-11-12
PostgreSQL 8.4 TriLUG 2009-11-12Andrew Dunstan
 
Python scripting kick off
Python scripting kick offPython scripting kick off
Python scripting kick offAndrea Gangemi
 
Article link httpiveybusinessjournal.compublicationmanaging-.docx
Article link httpiveybusinessjournal.compublicationmanaging-.docxArticle link httpiveybusinessjournal.compublicationmanaging-.docx
Article link httpiveybusinessjournal.compublicationmanaging-.docxfredharris32
 
Javascript part1
Javascript part1Javascript part1
Javascript part1Raghu nath
 
The GO Language : From Beginners to Gophers
The GO Language : From Beginners to GophersThe GO Language : From Beginners to Gophers
The GO Language : From Beginners to GophersAlessandro Sanino
 
The ProblemUsing C programming language write a program that simul.pdf
The ProblemUsing C programming language write a program that simul.pdfThe ProblemUsing C programming language write a program that simul.pdf
The ProblemUsing C programming language write a program that simul.pdffederaleyecare
 
An Overview of SystemVerilog for Design and Verification
An Overview of SystemVerilog  for Design and VerificationAn Overview of SystemVerilog  for Design and Verification
An Overview of SystemVerilog for Design and VerificationKapilRaghunandanTrip
 
Mysqlppt
MysqlpptMysqlppt
MysqlpptReka
 
Dynamic websites lec3
Dynamic websites lec3Dynamic websites lec3
Dynamic websites lec3Belal Arfa
 
My programming final proj. (1)
My programming final proj. (1)My programming final proj. (1)
My programming final proj. (1)aeden_brines
 
Domain Specific Languages In Scala Duse3
Domain Specific Languages In Scala Duse3Domain Specific Languages In Scala Duse3
Domain Specific Languages In Scala Duse3Peter Maas
 

Similar to Eff Plsql (20)

Database & Technology 1 _ Tom Kyte _ Efficient PL SQL - Why and How to Use.pdf
Database & Technology 1 _ Tom Kyte _ Efficient PL SQL - Why and How to Use.pdfDatabase & Technology 1 _ Tom Kyte _ Efficient PL SQL - Why and How to Use.pdf
Database & Technology 1 _ Tom Kyte _ Efficient PL SQL - Why and How to Use.pdf
 
How to tune a query - ODTUG 2012
How to tune a query - ODTUG 2012How to tune a query - ODTUG 2012
How to tune a query - ODTUG 2012
 
Input-output
Input-outputInput-output
Input-output
 
TAUS USER CONFERENCE 2009, Normalization of translation memories
TAUS USER CONFERENCE 2009, Normalization of translation memoriesTAUS USER CONFERENCE 2009, Normalization of translation memories
TAUS USER CONFERENCE 2009, Normalization of translation memories
 
PLSQLmy Updated (1).pptx
PLSQLmy Updated (1).pptxPLSQLmy Updated (1).pptx
PLSQLmy Updated (1).pptx
 
PHP tips by a MYSQL DBA
PHP tips by a MYSQL DBAPHP tips by a MYSQL DBA
PHP tips by a MYSQL DBA
 
Bioinformatica 27-10-2011-p4-files
Bioinformatica 27-10-2011-p4-filesBioinformatica 27-10-2011-p4-files
Bioinformatica 27-10-2011-p4-files
 
PostgreSQL 8.4 TriLUG 2009-11-12
PostgreSQL 8.4 TriLUG 2009-11-12PostgreSQL 8.4 TriLUG 2009-11-12
PostgreSQL 8.4 TriLUG 2009-11-12
 
Mp lab manual
Mp lab manualMp lab manual
Mp lab manual
 
Python scripting kick off
Python scripting kick offPython scripting kick off
Python scripting kick off
 
Article link httpiveybusinessjournal.compublicationmanaging-.docx
Article link httpiveybusinessjournal.compublicationmanaging-.docxArticle link httpiveybusinessjournal.compublicationmanaging-.docx
Article link httpiveybusinessjournal.compublicationmanaging-.docx
 
Javascript part1
Javascript part1Javascript part1
Javascript part1
 
The GO Language : From Beginners to Gophers
The GO Language : From Beginners to GophersThe GO Language : From Beginners to Gophers
The GO Language : From Beginners to Gophers
 
pm1
pm1pm1
pm1
 
The ProblemUsing C programming language write a program that simul.pdf
The ProblemUsing C programming language write a program that simul.pdfThe ProblemUsing C programming language write a program that simul.pdf
The ProblemUsing C programming language write a program that simul.pdf
 
An Overview of SystemVerilog for Design and Verification
An Overview of SystemVerilog  for Design and VerificationAn Overview of SystemVerilog  for Design and Verification
An Overview of SystemVerilog for Design and Verification
 
Mysqlppt
MysqlpptMysqlppt
Mysqlppt
 
Dynamic websites lec3
Dynamic websites lec3Dynamic websites lec3
Dynamic websites lec3
 
My programming final proj. (1)
My programming final proj. (1)My programming final proj. (1)
My programming final proj. (1)
 
Domain Specific Languages In Scala Duse3
Domain Specific Languages In Scala Duse3Domain Specific Languages In Scala Duse3
Domain Specific Languages In Scala Duse3
 

Recently uploaded

Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGSujit Pal
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...HostedbyConfluent
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 

Recently uploaded (20)

Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAG
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 

Eff Plsql

  • 1. Effective PL/SQL Thomas Kyte http://asktom.oracle.com/
  • 2.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11. Write as Little as you can
  • 12.
  • 13.
  • 14.
  • 15. insert into t ( .... ) select EMPNO, STATUS_DATE, .... from t1, t2, t3, t4, .... where ....; loop delete from t where (EMPNO,STATUS_DATE) in ( select EMPNO, min(STATUS_DATE) from t group by EMPNO having count(1) > 1 ); exit when sql%rowcount = 0; end loop; For any set of records with more than one EMPNO, remove rows with the oldest STATUS_DATE. Additionally – If the last set of EMPNO records all have the same STATUS_DATE, remove them all. More Code = More Bugs Less Code = Less Bugs EMPNO STATUS_DATE ------- ------------ 1 01-jan-2009 1 15-jun-2009 1 01-sep-2009 … 1000 01-feb-2009 1000 22-aug-2009 1000 10-oct-2009 1000 10-oct-2009 EMPNO STATUS_DATE ------- ------------ 1 01-sep-2009 … (1,01-jan-2009,3) (1001,01-feb-2009,4) EMPNO STATUS_DATE ------- ------------ 1 01-jan-2009 1 15-jun-2009 1 01-sep-2009 … 1000 01-feb-2009 1000 22-aug-2009 1000 10-oct-2009 1000 10-oct-2009 EMPNO STATUS_DATE ------- ------------ 1 01-jan-2009 1 15-jun-2009 1 01-sep-2009 … 1000 01-feb-2009 1000 22-aug-2009 1000 10-oct-2009 1000 10-oct-2009 (1,15-jun-2009,2) (1001,22-aug-2009,3) EMPNO STATUS_DATE ------- ------------ 1 01-jan-2009 1 15-jun-2009 1 01-sep-2009 … 1000 01-feb-2009 1000 22-aug-2009 1000 10-oct-2009 1000 10-oct-2009 (1001,22-aug-2009,2)
  • 16.
  • 17. /* Load table t using history tables. History tables have multiple records per employee. We need to keep the history records for each employee that have the maximum status date for that employee. We do that by computing the max(status_date) for each employee (partition by EMPNO finding max(status_date) and keeping only the records such that the status_date for that record = max(status_date) for all records with same empno */ insert /* APPEND */ into t ( .... ) select EMPNO, STATUS_DATE, ...... from ( select EMPNO, STATUS_DATE, .... , max(STATUS_DATE) OVER ( partition by EMPNO ) max_sd from t1, t2, t3, t4, … where … ) where STATUS_DATE = max_sd; More Code = More Bugs Less Code = Less Bugs
  • 18. /* Load table t using history tables. History tables have multiple records per employee. We need to keep the history records for each employee that have the maximum status date for that employee. We do that by numbering each history record by empno, keeping only the records such that it is the first record for a EMPNO after sorting by status_date desc. REALIZE: this is not deterministic if there are two status_dates that are the same for a given employee! */ insert /* APPEND */ into t ( .... ) select EMPNO, STATUS_DATE, ...... from ( select EMPNO, STATUS_DATE, .... , row_number() OVER ( partition by EMPNO order by STATUS_DATE desc ) rn from t1, t2, t3, t4, … where … ) where rn=1; More Code = More Bugs Less Code = Less Bugs
  • 19.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25. Use Static SQL
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 32.
  • 33.
  • 34.
  • 35. Bulk Processing create or replace procedure bulk as type ridArray is table of rowid; type onameArray is table of t.object_name%type; cursor c is select rowid rid, object_name from t t_bulk; l_rids ridArray; l_onames onameArray; N number := 100; begin open c; loop fetch c bulk collect into l_rids, l_onames limit N; for i in 1 .. l_rids.count loop l_onames(i) := substr(l_onames(i),2) ||substr(l_onames(i),1,1); end loop; forall i in 1 .. l_rids.count update t set object_name = l_onames(i) where rowid = l_rids(i); exit when c%notfound; end loop; close c; end; create or replace procedure slow_by_slow as begin for x in (select rowid rid, object_name from t t_slow_by_slow) loop x.object_name := substr(x.object_name,2) ||substr(x.object_name,1,1); update t set object_name = x.object_name where rowid = x.rid; end loop; end;
  • 36. Bulk Processing SELECT ROWID RID, OBJECT_NAME FROM T T_BULK call count cpu elapsed disk query current rows ------- ------ -------- ---------- ---------- ---------- ---------- ---------- total 721 0.17 0.17 0 22582 0 71825 ******************************************************************************** UPDATE T SET OBJECT_NAME = :B1 WHERE ROWID = :B2 call count cpu elapsed disk query current rows ------- ------ -------- ---------- ---------- ---------- ---------- ---------- Parse 1 0.00 0.00 0 0 0 0 Execute 719 12.83 13.77 0 71853 74185 71825 Fetch 0 0.00 0.00 0 0 0 0 ------- ------ -------- ---------- ---------- ---------- ---------- ---------- total 720 12.83 13.77 0 71853 74185 71825 SELECT ROWID RID, OBJECT_NAME FROM T T_SLOW_BY_SLOW call count cpu elapsed disk query current rows ------- ------ -------- ---------- ---------- ---------- ---------- ---------- total 721 0.17 0.17 0 22582 0 71825 ******************************************************************************** UPDATE T SET OBJECT_NAME = :B2 WHERE ROWID = :B1 call count cpu elapsed disk query current rows ------- ------ -------- ---------- ---------- ---------- ---------- ---------- Parse 1 0.00 0.00 0 0 0 0 Execute 71824 21.25 22.25 0 71836 73950 71824 Fetch 0 0.00 0.00 0 0 0 0 ------- ------ -------- ---------- ---------- ---------- ---------- ---------- total 71825 21.25 22.25 0 71836 73950 71824
  • 37. But of course, the bulkier the better… SELECT ROWID RID, OBJECT_NAME FROM T T_BULK call count cpu elapsed disk query current rows ------- ------ -------- ---------- ---------- ---------- ---------- ---------- total 721 0.17 0.17 0 22582 0 71825 ******************************************************************************** UPDATE T SET OBJECT_NAME = :B1 WHERE ROWID = :B2 call count cpu elapsed disk query current rows ------- ------ -------- ---------- ---------- ---------- ---------- ---------- Parse 1 0.00 0.00 0 0 0 0 Execute 719 12.83 13.77 0 71853 74185 71825 Fetch 0 0.00 0.00 0 0 0 0 ------- ------ -------- ---------- ---------- ---------- ---------- ---------- total 720 12.83 13.77 0 71853 74185 71825 update t set object_name = substr(object_name,2) || substr(object_name,1,1) call count cpu elapsed disk query current rows ------- ------ -------- ---------- ---------- ---------- ---------- ---------- Parse 1 0.00 0.00 0 0 0 0 Execute 1 1.30 1.44 0 2166 75736 71825 Fetch 0 0.00 0.00 0 0 0 0 ------- ------ -------- ---------- ---------- ---------- ---------- ---------- total 2 1.30 1.44 0 2166 75736 71825 Lots less code too! (dml error logging if you need)
  • 39.
  • 40. Using Invokers Rights
  • 41.
  • 42. Invokers Rights ops$tkyte%ORA11GR2> create table t 2 as 3 select 'hello world' text 4 from dual 5 / Table created. ops$tkyte%ORA11GR2> create or replace procedure IR 2 as 3 begin 4 for x in ( select * from t) 5 loop 6 dbms_output.put_line(x.text); 7 end loop; 8 end; 9 / Procedure created. ops$tkyte%ORA11GR2> grant all on ops$tkyte.ir to public; Grant succeeded. ops$tkyte%ORA11GR2> create or replace procedure DR 2 AUTHID CURRENT_USER 3 as 4 begin 5 for x in ( select * from t) 6 loop 7 dbms_output.put_line(x.text); 8 end loop; 9 end; 10 / Procedure created. ops$tkyte%ORA11GR2> grant all on ops$tkyte.dr to public; Grant succeeded.
  • 43. ops$tkyte%ORA11GR2> connect scott/tiger Connected. scott%ORA11GR2> exec ops$tkyte.ir hello world PL/SQL procedure successfully completed. scott%ORA11GR2> exec ops$tkyte.dr BEGIN ops$tkyte.dr; END; * ERROR at line 1: ORA-00942: table or view does not exist ORA-06512: at &quot;OPS$TKYTE.DR&quot;, line 5 ORA-06512: at line 1 scott%ORA11GR2> connect / Connected. ops$tkyte%ORA11GR2> grant select on t to scott; Grant succeeded. ops$tkyte%ORA11GR2> connect scott/tiger Connected. scott%ORA11GR2> exec ops$tkyte.dr BEGIN ops$tkyte.dr; END; * ERROR at line 1: ORA-00942: table or view does not exist ORA-06512: at &quot;OPS$TKYTE.DR&quot;, line 5 ORA-06512: at line 1 Invokers Rights
  • 44. scott%ORA11GR2> connect / Connected. ops$tkyte%ORA11GR2> create or replace procedure dr 2 AUTHID CURRENT_USER 3 as 4 begin 5 for x in ( select * from OPS$TKYTE.t) 6 loop 7 dbms_output.put_line(x.text); 8 end loop; 9 end; 10 / Procedure created. ops$tkyte%ORA11GR2> connect scott/tiger Connected. scott%ORA11GR2> exec ops$tkyte.dr hello world PL/SQL procedure successfully completed. scott%ORA11GR2> connect / Connected. ops$tkyte%ORA11GR2> revoke select on t from scott; Revoke succeeded. ops$tkyte%ORA11GR2> connect scott/tiger Connected. scott%ORA11GR2> exec ops$tkyte.dr BEGIN ops$tkyte.dr; END; * ERROR at line 1: ORA-00942: table or view does not exist ORA-06512: at &quot;OPS$TKYTE.DR&quot;, line 5 ORA-06512: at line 1 Invokers Rights
  • 45.
  • 46.
  • 47. Implicit versus Explicit
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 56.
  • 57.
  • 58. When others then null; ops$tkyte%ORA11GR2> create table t( x varchar2(4000) ); Table created. ops$tkyte%ORA11GR2> create or replace 2 procedure maintain_t 3 ( p_str in varchar2 ) 4 as 5 begin 6 insert into t (x) values ( 'hello' ); 7 insert into t (x) values ( p_str ); 8 insert into t (x) values ( 'world' ); 9 exception 10 when others 11 then 12 -- call some log_error() routine 13 null; 14 end; 15 / Procedure created. ops$tkyte%ORA11GR2> exec maintain_t( rpad( 'x', 4001, 'x' ) ); PL/SQL procedure successfully completed. ops$tkyte%ORA11GR2> select * from t; X -------------------- hello 1 row selected.
  • 59. When others then null; ops$tkyte%ORA11GR2> alter procedure maintain_t compile 2 PLSQL_Warnings = 'enable:all' 3 reuse settings 4 / SP2-0805: Procedure altered with compilation warnings ops$tkyte%ORA11GR2> show errors procedure maintain_t Errors for PROCEDURE MAINTAIN_T: LINE/COL ERROR -------- ----------------------------------------------------------------- 1/1 PLW-05018: unit MAINTAIN_T omitted optional AUTHID clause; default value DEFINER used 9/8 PLW-06009: procedure &quot;MAINTAIN_T&quot; OTHERS handler does not end in RAISE or RAISE_APPLICATION_ERROR
  • 60.
  • 61. When others then null; ops$tkyte%ORA11GR2> create table t( x varchar2(4000) ); Table created. ops$tkyte%ORA11GR2> create or replace 2 procedure maintain_t 3 ( p_str in varchar2 ) 4 as 5 begin 6 insert into t (x) values ( 'hello' ); 7 insert into t (x) values ( p_str ); 8 insert into t (x) values ( 'world' ); 9 exception 10 when others 11 then 12 -- call some log_error() routine 13 RAISE; 14 end; 15 / Procedure created. ops$tkyte%ORA11GR2> exec maintain_t( rpad( 'x', 4001, 'x' ) ); BEGIN maintain_t( rpad( 'x', 4001, 'x' ) ); END; * ERROR at line 1: ORA-01461: can bind a LONG value only for insert into a LONG column ORA-06512: at &quot;OPS$TKYTE.MAINTAIN_T&quot;, line 12 ORA-06512: at line 1 ops$tkyte%ORA11GR2> select * from t; no rows selected
  • 62.
  • 63.
  • 64. Things to do…
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.