SlideShare une entreprise Scribd logo
1  sur  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]
 

Contenu connexe

Tendances

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
 

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

En vedette

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
 

En vedette (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
 

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

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

Dernier

Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Wonjun Hwang
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfRankYa
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024The Digital Insurer
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clashcharlottematthew16
 

Dernier (20)

Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdf
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clash
 

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.