<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments on: Wrong use of constant packages</title>
	<atom:link href="http://technology.amis.nl/2006/05/22/wrong-use-of-constant-packages/feed/" rel="self" type="application/rss+xml" />
	<link>http://technology.amis.nl/2006/05/22/wrong-use-of-constant-packages/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=wrong-use-of-constant-packages</link>
	<description></description>
	<lastBuildDate>Fri, 12 Apr 2013 10:04:09 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
	<item>
		<title>By: Pasko</title>
		<link>http://technology.amis.nl/2006/05/22/wrong-use-of-constant-packages/#comment-3294</link>
		<dc:creator>Pasko</dc:creator>
		<pubDate>Fri, 09 Feb 2007 17:04:37 +0000</pubDate>
		<guid isPermaLink="false">http://technology.amis.nl/blog/?p=1202#comment-3294</guid>
		<description><![CDATA[Hi,
Great Discussion!
For existing Projects i would pick the Solution suggested by Andre.
I think it&#039;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&#039;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) := &#039;Andre&#039;;
    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 &#039;Andre&#039;;
    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]]></description>
		<content:encoded><![CDATA[<p>Hi,<br />
Great Discussion!<br />
For existing Projects i would pick the Solution suggested by Andre.<br />
I think it&#8217;s Great and Flexible.</p>
<p>Now,my suggestion for New Projects:<br />
just create all Constants as Functions and write a Package Body for each Function<br />
and return the respective Values for Constants.</p>
<p>This has the Advantage that it&#8217;s Type Safe because i can specify the Return Type in the Function.<br />
The only Disadvantage here is that one has to write too much code <img src='http://technology.amis.nl/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  but for this we could<br />
write PL-SQL to generate this Package automatically by selecting from a Table where all our<br />
constants are temporarily stored, for instance from table my_constants from Andre.</p>
<p>Oh, one more Disadvantage is that if we have a New Constant then we have to change the Package Spec and Body;<br />
i would have preferred a Solution whereby a Constant Addition would not have necessitated a package Change.</p>
<p>So for example:</p>
<p>create or replace package my_constants<br />
is<br />
  &#8211;my_name constant varchar2(30) := &#8216;Andre&#8217;;<br />
    function my_name   return varchar2 ;<br />
    function my_salary  return number   ;<br />
end;<br />
/</p>
<p>create or replace package body my_constants<br />
is</p>
<p>    function my_name<br />
     return varchar2<br />
    is<br />
    begin<br />
      return &#8216;Andre&#8217;;<br />
    end ;</p>
<p>    function my_salary<br />
      return number<br />
    is<br />
    begin<br />
       return 200000;<br />
    end my_salary;<br />
     &#8211;add more functions for each new constant here<br />
end;<br />
/</p>
<p>select my_constants.MY_NAME from dual<br />
/</p>
<p>What do you think about this Solution?</p>
<p>Regards,</p>
<p>Pasko</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: mrskin</title>
		<link>http://technology.amis.nl/2006/05/22/wrong-use-of-constant-packages/#comment-3293</link>
		<dc:creator>mrskin</dc:creator>
		<pubDate>Sat, 30 Sep 2006 22:12:16 +0000</pubDate>
		<guid isPermaLink="false">http://technology.amis.nl/blog/?p=1202#comment-3293</guid>
		<description><![CDATA[Just wanted to say thanks for the article.]]></description>
		<content:encoded><![CDATA[<p>Just wanted to say thanks for the article.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Niall Mc Phillips</title>
		<link>http://technology.amis.nl/2006/05/22/wrong-use-of-constant-packages/#comment-3292</link>
		<dc:creator>Niall Mc Phillips</dc:creator>
		<pubDate>Mon, 12 Jun 2006 11:49:03 +0000</pubDate>
		<guid isPermaLink="false">http://technology.amis.nl/blog/?p=1202#comment-3292</guid>
		<description><![CDATA[Not sure if I&#039;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 := &#039;EN&#039;;
  c_lang_fr                      CONSTANT languages.language_code%TYPE := &#039;FR&#039;;
  c_lang_es                      CONSTANT languages.language_code%TYPE := &#039;ES&#039;;
  --
  --   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 &#039;BEGIN myConst.g_bidon := myConst.&#039;&#124;&#124;p_constant_name&#124;&#124;&#039;; END; &#039;;
  RETURN g_bidon;
END getConstant;

END myConst;]]></description>
		<content:encoded><![CDATA[<p>Not sure if I&#8217;m missing the point &#8230; but here is a package that appears to do the job (cut down for legibility)</p>
<p>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.</p>
<p>PACKAGE myConst IS<br />
  &#8211;<br />
  g_bidon                        VARCHAR2(32767) := NULL;<br />
  &#8211;<br />
  &#8212; lang code<br />
  &#8211;<br />
  c_lang_en                      CONSTANT languages.language_code%TYPE := &#8216;EN&#8217;;<br />
  c_lang_fr                      CONSTANT languages.language_code%TYPE := &#8216;FR&#8217;;<br />
  c_lang_es                      CONSTANT languages.language_code%TYPE := &#8216;ES&#8217;;<br />
  &#8211;<br />
  &#8212;   Functions<br />
  &#8211;<br />
  FUNCTION getConstant (p_constant_name IN VARCHAR2 DEFAULT NULL)<br />
    RETURN VARCHAR2;<br />
  &#8211;<br />
END myConst;</p>
<p>PACKAGE BODY myConst IS</p>
<p>FUNCTION getConstant (p_constant_name IN VARCHAR2 DEFAULT NULL)<br />
  RETURN VARCHAR2 IS<br />
    v_return  VARCHAR2(2000);<br />
BEGIN<br />
  EXECUTE IMMEDIATE &#8216;BEGIN myConst.g_bidon := myConst.&#8217;||p_constant_name||&#8217;; END; &#8216;;<br />
  RETURN g_bidon;<br />
END getConstant;</p>
<p>END myConst;</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Marco Gralike</title>
		<link>http://technology.amis.nl/2006/05/22/wrong-use-of-constant-packages/#comment-3291</link>
		<dc:creator>Marco Gralike</dc:creator>
		<pubDate>Wed, 24 May 2006 21:25:12 +0000</pubDate>
		<guid isPermaLink="false">http://technology.amis.nl/blog/?p=1202#comment-3291</guid>
		<description><![CDATA[alter table ... cache;]]></description>
		<content:encoded><![CDATA[<p>alter table &#8230; cache;</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Andre Crone</title>
		<link>http://technology.amis.nl/2006/05/22/wrong-use-of-constant-packages/#comment-3290</link>
		<dc:creator>Andre Crone</dc:creator>
		<pubDate>Tue, 23 May 2006 10:30:08 +0000</pubDate>
		<guid isPermaLink="false">http://technology.amis.nl/blog/?p=1202#comment-3290</guid>
		<description><![CDATA[@Mr Ed.
Steve Adams mentioned singe table hash clusters, I didnt.

@Harm
I didn&#039;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.]]></description>
		<content:encoded><![CDATA[<p>@Mr Ed.<br />
Steve Adams mentioned singe table hash clusters, I didnt.</p>
<p>@Harm<br />
I didn&#8217;t write the original code. This function would have never existed if it was up to me.</p>
<p>@Wilfred<br />
We have a webapplication with short living sessions. Memory is not possible for us.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Alex Gorbachev</title>
		<link>http://technology.amis.nl/2006/05/22/wrong-use-of-constant-packages/#comment-3289</link>
		<dc:creator>Alex Gorbachev</dc:creator>
		<pubDate>Tue, 23 May 2006 09:29:29 +0000</pubDate>
		<guid isPermaLink="false">http://technology.amis.nl/blog/?p=1202#comment-3289</guid>
		<description><![CDATA[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. :)]]></description>
		<content:encoded><![CDATA[<p>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. <img src='http://technology.amis.nl/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Alex Gorbachev</title>
		<link>http://technology.amis.nl/2006/05/22/wrong-use-of-constant-packages/#comment-3288</link>
		<dc:creator>Alex Gorbachev</dc:creator>
		<pubDate>Tue, 23 May 2006 09:25:50 +0000</pubDate>
		<guid isPermaLink="false">http://technology.amis.nl/blog/?p=1202#comment-3288</guid>
		<description><![CDATA[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&#039;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&#039;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&#039;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.]]></description>
		<content:encoded><![CDATA[<p>Thanks for sharing this real life experience. Few comments that might help to improve it further.</p>
<p>Both old and new solutions have another problem that is not mentioned here. It&#8217;s very insecure &#8211; 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 &#8211; you never know where it exposed and who gets access to the function.</p>
<p>With redesign you have introduced another problem. Though less significant than hard parse &#8211; it&#8217;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.</p>
<p>Another disadvantage of both solutions is the package itself &#8211; 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.</p>
<p>After all that I would question if you really need package constants anymore. Isn&#8217;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.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Olof</title>
		<link>http://technology.amis.nl/2006/05/22/wrong-use-of-constant-packages/#comment-3287</link>
		<dc:creator>Olof</dc:creator>
		<pubDate>Tue, 23 May 2006 08:09:44 +0000</pubDate>
		<guid isPermaLink="false">http://technology.amis.nl/blog/?p=1202#comment-3287</guid>
		<description><![CDATA[Why your fonction uses &#039;execute_immediate&#039; ? Why not a simple &#039;return my_name;&#039; ???]]></description>
		<content:encoded><![CDATA[<p>Why your fonction uses &#8216;execute_immediate&#8217; ? Why not a simple &#8216;return my_name;&#8217; ???</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: karl</title>
		<link>http://technology.amis.nl/2006/05/22/wrong-use-of-constant-packages/#comment-3286</link>
		<dc:creator>karl</dc:creator>
		<pubDate>Mon, 22 May 2006 22:47:21 +0000</pubDate>
		<guid isPermaLink="false">http://technology.amis.nl/blog/?p=1202#comment-3286</guid>
		<description><![CDATA[@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]]></description>
		<content:encoded><![CDATA[<p>@Francois<br />
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.<br />
Youd could even mark the type of the parameter.<br />
Greetings<br />
Karl</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Wilfred</title>
		<link>http://technology.amis.nl/2006/05/22/wrong-use-of-constant-packages/#comment-3285</link>
		<dc:creator>Wilfred</dc:creator>
		<pubDate>Mon, 22 May 2006 22:21:56 +0000</pubDate>
		<guid isPermaLink="false">http://technology.amis.nl/blog/?p=1202#comment-3285</guid>
		<description><![CDATA[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 &quot;caches&quot; 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&#039;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&#039;t run the risk of an outdated database &quot;cache&quot; table. The caching is all done in a package (&quot;session&quot;) 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)]]></description>
		<content:encoded><![CDATA[<p>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.</p>
<p>Two things we did:<br />
1) make the function DETERMINISTIC. Oracle 10gR2 &#8220;caches&#8221; the result and only executes the function once for a SQL statement, even if the constant is required in something like a nested loop.<br />
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&#8217;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.<br />
This way you don&#8217;t run the risk of an outdated database &#8220;cache&#8221; table. The caching is all done in a package (&#8220;session&#8221;) 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.</p>
<p>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.</p>
<p>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)</p>
]]></content:encoded>
	</item>
</channel>
</rss>
