Escolar Documentos
Profissional Documentos
Cultura Documentos
In this post we’re going to analyze all the five PRAGMA directives of Oracle’s PL/SQL. Four of them
exist since Oracle8i while the last one has been introduced with Oracle11g.
We need a function that converts a string to a date using the ‘YYYY-MM-DD’ format:
1
2 SQL> create or replace function string2date (str in varchar2) return
3 date is
4 2 retDate date;
3 begin
5 4 retDate := to_date(str,'yyyy-mm-dd');
6 5 return retDate;
7 6 end;
8 7 /
9
10
11 SQL> select string2date('2010-01-31')
2 from dual;
12
13 STRING2DA
14 ---------
15 31-JAN-10
16
17 SQL> select string2date('werrwer')
2 from dual;
18 select string2date('werrwer')
19 *
20 ERROR at line 1:
21 ORA-01841: (full) year must be between -4713 and +9999, and not be 0
22 ORA-06512: at "MAXR.STRING2DATE", line 4
23
As the example shows, if the input string does not conform to the format we get the ORA-1841
error.
We want to manage this error using the PRAGMA EXCEPTION_INIT directive:
We’re defining a new exception not_valid_date, but it will be never called if we don’t associate it
to the ORA-1841 error using the PRAGMA.
Once we have made the association Oracle knows that, in case of the ORA-1841 error, the
not_valid_date exception must be raised.
In some situations, only functions that guarantee those restrictions can be used.
The following is a simple example:
Let’s define a package made of a single function that updates a db table and returns a number:
If we try to use the function pack.a in a query statement we’ll get an error:
PL/SQL functions can be used inside a query statement only if they don’t modify neither the db
nor packages’ variables.
This error can be descovered only at runtime, when the select statement is executed.
How can we check for this errors at compile time? We can use PRAGMA RESTRICT_REFERENCES!
If we know that the function will be used in SQL we can define it as follows:
Declaring that the function A will not modify the database state (WNDS stands for WRITE NO
DATABASE STATE).
Once we have made this declaration, if a programmer, not knowing that the function has to be
used in a query statement, tries to write code for A that violates the PRAGMA:
Pragma RESTRICT_REFERENCE is deprecated and could be removed from future versions of Oracle.
PRAGMA SERIALLY_REUSABLE tells to the compiler that the package’s variables are needed for
a single use. After this single use Oracle can free the associated memory. It’s really useful to save
memory when a packages uses large temporary space just once in the session.
Let’s see an example.
Let’s define a package with a single numeric variable “var” not initialized:
If we assign a value to var, this will preserve that value for the whole session:
1 SQL> begin
2 2 pack.var := 1;
3 3 end;
4 4 /
5
6 SQL> exec dbms_output.put_line('Var='||pack.var);
Var=1
7
If we use the PRAGMA SERIALLY_REUSABLE, var will preserve the value just inside the program
that initializes it, but is null in the following calls:
PRAGMA SERIALLY_REUSABLE is a way to change the default behavior of package variables that
is as useful as heavy for memory.
Let’s define two functions that do exactly the same thing, read and return the sum of salaries of
EMP:
The second one uses the PRAGMA AUTONOMOUS_TRANSACTION. Now let’s cut all the salaries:
GETSAL is seeing uncommitted changed data while GETSAL_AT, defined using PRAGMA
AUTONOMOUS_TRANSACTION, reads data as they where before the UPDATE statement…
In Oracle11g has been added a new feature that optimizer can use to get better performances, it’s
called Subprogram Inlining.
Optimizer can (autonomously or on demand) choose to replace a subprogram call with a local copy
of the subprogram.
1 declare
2 total number;
3 begin
4 total := calculate_nominal + calculate_interests;
end;
5
1
declare
2 total number;
3 v_calculate_nominal number;
4 v_calculate_interests number;
5 begin
6 select sum(nominal)
into v_calculate_nominal
7 from deals;
8
9 select sum(interest)
10 into v_calculate_interests
11 from deals;
12
total := v_calculate_nominal +
13
v_calculate_interests;
14 end;
15
PRAGMA INLINE is the tool that we own to drive this new feature.
If we don’t want such an optimization we can do:
1
declare
2 total number;
3 begin
4 PRAGMA INLINE(calculate_nominal,'NO');
5 PRAGMA INLINE(calculate_interests,'NO');
total := calculate_nominal + calculate_interests;
6 end;
7
declare
1 total number;
2 begin
3 PRAGMA INLINE(calculate_nominal,'YES');
total := calculate_nominal + calculate_interests;
4 end;
5
6
Subprogram inlining behave differently depending on the level of optimization defined through the
db initialization variable PLSQL_OPTIMIZE_LEVEL.
If this variable is set to 2 (that’s the default value) optimizer never uses subprogram inlining unless
the programmer requests it using PRAGMA INLINE YES.
If PLSQL_OPTIMIZE_LEVEL=3 optimizer can autonomously decide whether to use subprogram
inlining or not. In this case PRAGMA INLINE YES does not force the optimizer, it’s just an hint.