Comments on: Wrong use of constant packages http://technology.amis.nl/2006/05/22/wrong-use-of-constant-packages/ Friends of Oracle and Java Mon, 24 Nov 2014 11:49:17 +0000 hourly 1 http://wordpress.org/?v=4.0.1 By: Pasko http://technology.amis.nl/2006/05/22/wrong-use-of-constant-packages/#comment-3294 Fri, 09 Feb 2007 17:04:37 +0000 http://technology.amis.nl/blog/?p=1202#comment-3294 Hi,
Great Discussion!
For existing Projects i would pick the Solution suggested by Andre.
I think it’s Great and Flexible.

Now,my suggestion for New Projects:
just create all Constants as Functions and write a Package Body for each Function
and return the respective Values for Constants.

This has the Advantage that it’s Type Safe because i can specify the Return Type in the Function.
The only Disadvantage here is that one has to write too much code :) but for this we could
write PL-SQL to generate this Package automatically by selecting from a Table where all our
constants are temporarily stored, for instance from table my_constants from Andre.

Oh, one more Disadvantage is that if we have a New Constant then we have to change the Package Spec and Body;
i would have preferred a Solution whereby a Constant Addition would not have necessitated a package Change.

So for example:

create or replace package my_constants
is
–my_name constant varchar2(30) := ‘Andre';
function my_name return varchar2 ;
function my_salary return number ;
end;
/

create or replace package body my_constants
is

function my_name
return varchar2
is
begin
return ‘Andre';
end ;

function my_salary
return number
is
begin
return 200000;
end my_salary;
–add more functions for each new constant here
end;
/

select my_constants.MY_NAME from dual
/

What do you think about this Solution?

Regards,

Pasko

]]>
By: mrskin http://technology.amis.nl/2006/05/22/wrong-use-of-constant-packages/#comment-3293 Sat, 30 Sep 2006 22:12:16 +0000 http://technology.amis.nl/blog/?p=1202#comment-3293 Just wanted to say thanks for the article.

]]>
By: Niall Mc Phillips http://technology.amis.nl/2006/05/22/wrong-use-of-constant-packages/#comment-3292 Mon, 12 Jun 2006 11:49:03 +0000 http://technology.amis.nl/blog/?p=1202#comment-3292 Not sure if I’m missing the point … but here is a package that appears to do the job (cut down for legibility)

It uses the string global g_bidon to return a value. The disadvantage is that the value is always a string. But I suppose that functions could be added to cater for other data types.

PACKAGE myConst IS

g_bidon VARCHAR2(32767) := NULL;

— lang code

c_lang_en CONSTANT languages.language_code%TYPE := ‘EN';
c_lang_fr CONSTANT languages.language_code%TYPE := ‘FR';
c_lang_es CONSTANT languages.language_code%TYPE := ‘ES';

— Functions

FUNCTION getConstant (p_constant_name IN VARCHAR2 DEFAULT NULL)
RETURN VARCHAR2;

END myConst;

PACKAGE BODY myConst IS

FUNCTION getConstant (p_constant_name IN VARCHAR2 DEFAULT NULL)
RETURN VARCHAR2 IS
v_return VARCHAR2(2000);
BEGIN
EXECUTE IMMEDIATE ‘BEGIN myConst.g_bidon := myConst.’||p_constant_name||'; END; ‘;
RETURN g_bidon;
END getConstant;

END myConst;

]]>
By: Marco Gralike http://technology.amis.nl/2006/05/22/wrong-use-of-constant-packages/#comment-3291 Wed, 24 May 2006 21:25:12 +0000 http://technology.amis.nl/blog/?p=1202#comment-3291 alter table … cache;

]]>
By: Andre Crone http://technology.amis.nl/2006/05/22/wrong-use-of-constant-packages/#comment-3290 Tue, 23 May 2006 10:30:08 +0000 http://technology.amis.nl/blog/?p=1202#comment-3290 @Mr Ed.
Steve Adams mentioned singe table hash clusters, I didnt.

@Harm
I didn’t write the original code. This function would have never existed if it was up to me.

@Wilfred
We have a webapplication with short living sessions. Memory is not possible for us.

]]>
By: Alex Gorbachev http://technology.amis.nl/2006/05/22/wrong-use-of-constant-packages/#comment-3289 Tue, 23 May 2006 09:29:29 +0000 http://technology.amis.nl/blog/?p=1202#comment-3289 Hehe, I wrote the comment above yesterday and it was stuck in my browser until today morning when I clicked submit. Now there are enough suggestions already but point about SQL injection is still valid. :)

]]>
By: Alex Gorbachev http://technology.amis.nl/2006/05/22/wrong-use-of-constant-packages/#comment-3288 Tue, 23 May 2006 09:25:50 +0000 http://technology.amis.nl/blog/?p=1202#comment-3288 Thanks for sharing this real life experience. Few comments that might help to improve it further.

Both old and new solutions have another problem that is not mentioned here. It’s very insecure – anyone having access to this function is able to ruin the whole aplication assuming that owner is able to perform DML or DDLs on objects. Since you have big application – you never know where it exposed and who gets access to the function.

With redesign you have introduced another problem. Though less significant than hard parse – it’s many selects of same row or rows in the same block. You can avoid it with PL/SQL tables that would cache values for the session.

Another disadvantage of both solutions is the package itself – anytime you change the constant you are at risk to make a mistake rendering the package status invalid and the whole application unable to read it. In the newer solution this risk is mitigated because chances are that value is cached into the table but there still can be misses.

After all that I would question if you really need package constants anymore. Isn’t having one single lookup table accessed via single function enough? This would solve all problems. If there contention issues arise than you can consider caching values in PL/SQL table (PL/SQL table is store in PGA for each session so no contention). The only reason to keep package can be that these constants are accessed from PL/SQL blocks much more often than via function now.

]]>
By: Olof http://technology.amis.nl/2006/05/22/wrong-use-of-constant-packages/#comment-3287 Tue, 23 May 2006 08:09:44 +0000 http://technology.amis.nl/blog/?p=1202#comment-3287 Why your fonction uses ‘execute_immediate’ ? Why not a simple ‘return my_name;’ ???

]]>
By: karl http://technology.amis.nl/2006/05/22/wrong-use-of-constant-packages/#comment-3286 Mon, 22 May 2006 22:47:21 +0000 http://technology.amis.nl/blog/?p=1202#comment-3286 @Francois
Paramter could be numeric or string so an additionally pl/sql collection as described would be fine to store the vals all to strings like the Environment in the korn shell.
Youd could even mark the type of the parameter.
Greetings
Karl

]]>
By: Wilfred http://technology.amis.nl/2006/05/22/wrong-use-of-constant-packages/#comment-3285 Mon, 22 May 2006 22:21:56 +0000 http://technology.amis.nl/blog/?p=1202#comment-3285 We had exactly the same problem. I did not use a database table, but the forementioned PL/SQL table. Especially when using the function in a SQL statement it might be executed hundreds or thousands of times for getting the same constant.

Two things we did:
1) make the function DETERMINISTIC. Oracle 10gR2 “caches” the result and only executes the function once for a SQL statement, even if the constant is required in something like a nested loop.
2) The get_constant function first checks in a package variable (PL/SQL table) if the constant is in that table. Initially the table is just empty. If the constant is in the table, return that value. If it’s not in the table, query it using dynamic SQL and store it in the PL/SQL table before returning the value. This bascially implements a PL/SQL caching table in memory.
This way you don’t run the risk of an outdated database “cache” table. The caching is all done in a package (“session”) variable. We found that the get_constant function is only performing the actual dynamic SQL a couple of times for a session since most of the get_constant calls tend to be for the same set of constants.

PS. You can use this PL/SQL caching table trick for all sorts of functions that you expect to be called multiple times with the same parameters.

It would be even better if you can have some sort of memory structure shared by all sessions to do the in-memory caching. This way all sessions benefit from a single session adding something to the cache. I cannot think of a way to do this in PL/SQL. Perhaps something with Java or an external process. (or would that be too much overhead)

]]>
By: harm http://technology.amis.nl/2006/05/22/wrong-use-of-constant-packages/#comment-3284 Mon, 22 May 2006 22:16:18 +0000 http://technology.amis.nl/blog/?p=1202#comment-3284 Hi Andre,
Your ‘get_my_constant’ function enables SQL injection. Bad.

]]>
By: Francois Degrelle http://technology.amis.nl/2006/05/22/wrong-use-of-constant-packages/#comment-3283 Mon, 22 May 2006 19:47:18 +0000 http://technology.amis.nl/blog/?p=1202#comment-3283 Because you use a table to store the values, you could initialize your package constants with the values of this table.
It would not be a big job.

]]>
By: Mr. Ed http://technology.amis.nl/2006/05/22/wrong-use-of-constant-packages/#comment-3282 Mon, 22 May 2006 19:40:06 +0000 http://technology.amis.nl/blog/?p=1202#comment-3282 What, Steve Adams didn’t mention single-table hash clusters? Shocking.

If the number of constants is low, a simple set of “if” statements might be faster:

if p_constant = “foo” then
return my_constants.foo;
else

end if;

Also, if you used PLSQL arrays, you don’t have to rewrite the constants package. Instead of using a table as a “cache”, you use the PLSQL arrays as a “cache”.

]]>
By: Andre Crone http://technology.amis.nl/2006/05/22/wrong-use-of-constant-packages/#comment-3281 Mon, 22 May 2006 18:00:37 +0000 http://technology.amis.nl/blog/?p=1202#comment-3281 @Karl:
I just have written a document here at the project describing how we could use context with our own namespaces. Yes they would greatly reduce the need for this package. And about the LIO’s. We now have two queries generating more LIO’s than my function call. I love statspack!!!! I will write a post about those two queries very soon. I just have to test my final results on a server on which I can be the DBA (that’s at home).

@francois:
That would be my ideal solution; but I would have to test it. But again I decided not to do so, because it would mean a complete rewrite of a very important package.

]]>
By: Francois http://technology.amis.nl/2006/05/22/wrong-use-of-constant-packages/#comment-3280 Mon, 22 May 2006 17:47:58 +0000 http://technology.amis.nl/blog/?p=1202#comment-3280 Nice tip.

Another kind of approach using a PL/SQL table:

CREATE OR REPLACE PACKAGE Pkg_Constants
AS
TYPE TYP_TAB_NUMBER IS TABLE OF NUMBER INDEX BY VARCHAR2(30) ;

tab_values TYP_TAB_NUMBER ;

FUNCTION Get_Value( PC$ParamName IN VARCHAR2 )
RETURN NUMBER ;

END Pkg_Constants;
/

CREATE OR REPLACE PACKAGE BODY Pkg_Constants
AS

FUNCTION Get_Value( PC$ParamName IN VARCHAR2 )
RETURN NUMBER
IS
BEGIN
RETURN tab_values( PC$ParamName ) ;
END ;

BEGIN
— initialisation phase —
tab_values( ‘param1′ ) := 1.0 ;
tab_values( ‘param5′ ) := 5.0 ;
tab_values( ‘param10′ ) := 10.0 ;

END Pkg_Constants;
/

SQL> select PKG_CONSTANTS.Get_Value(‘param10′) from dual
2 /

PKG_CONSTANTS.GET_VALUE(‘PARAM10′)
———————————-
10

SQL>

]]>