Skip to Main Content
  • Questions
  • Change value of CONSTANT declaration

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, Davide.

Asked: March 17, 2017 - 4:41 pm UTC

Last updated: March 20, 2017 - 2:29 pm UTC

Version: 11g

Viewed 1000+ times

You Asked

Hi,

in my code I defined a constant through a custom function that fetches some data from the DB and creates an instance of a custom type. if the return value of the function changes over time, I'm wondering which event trigger a refresh on that constant.
i'd like that happen daily or something like that.

here is the constant definition:

tppag_convers CONSTANT SER_REDD.TB_CHAR3 := ser_redd.fetchChar3Config('UMBR_FUND_CAUS_CONVERS');



tnkz


and Chris said...

If you want to change something's value, then it's "not a constant"!

Anyway, you can define PL/SQL package variables. The database initializes these for each session when you call the package.

For example, you can create a function which returns a value based on a SQL statement. The assign this to a package level variable:

create table t (
  x int 
);
insert into t values (1);
commit;

create or replace function f
  return t.x%type as 
  retval t.x%type ;
begin
  select x into retval from t;
  
  return retval;
end;
/

create or replace package pkg as
  v pls_integer := f;
  procedure p;
end pkg;
/

create or replace package body pkg as
  procedure p as
  begin
    dbms_output.put_line('The value of v is: ' || pkg.v);
  end p;
end pkg;
/

set serveroutput on
exec pkg.p;

The value of v is: 1


The package variable retains its value until the session ends. So if the function returns a new value, your variable stays the same:

update t set x = 2;
commit;

select f, x from t;

F  X  
2  2  

exec pkg.p;

The value of v is: 1


Other than closing all your sessions and starting new ones (generally not a great idea), there are a few ways to re-initialize the package variables:

- Recompile the package
- Reinitailize the variables using dbms_session

Continuing the example above:

alter package pkg compile;
exec pkg.p;

The value of v is: 2

update t set x = 3;
commit;

exec dbms_session.modify_package_state(dbms_session.reinitialize);
select f, x from t;

F  X  
3  3  

set serveroutput on
exec pkg.p;

The value of v is: 3


Recompiling your packages just to reset package state is a bad idea. And modify_package_state only affects the current session. So you'd need to find a way to call this in each session at the appropriate time.

Alternatively, you can declare the package as "serially_reusable". In this case, the package variables only persist for the duration of the call. So the code picks up any changes sooner:

delete t;
insert into t values (1);
commit;

create or replace package pkg as
  pragma serially_reusable;
  v pls_integer := f;
  procedure p;
end pkg;
/

create or replace package body pkg as
  pragma serially_reusable;
  procedure p as
  begin
    dbms_output.put_line('The value of v is: ' || pkg.v);
  end p;
end pkg;
/

set serveroutput on
exec pkg.p;

The value of v is: 1

update t set x = 2;
commit;

select * from t;

X  
2  

exec pkg.p;

The value of v is: 2


The problem here is the initialization will run for each new call. So if your package is "heavily executed" you're adding a lot of overhead executing the SQL providing the value over and over and over and over...

Rating

  (1 rating)

Is this answer out of date? If it is, please let us know via a Comment

Comments

tnkz

Davide Golinelli, March 20, 2017 - 6:32 pm UTC

i followed your advice: i've declared my "not so constant" var in this way:

tppag_storni SER_REDD.TB_CHAR3 := NULL;


end then, in the LOOP where i use it i've added this line of code:

tppag_storni := COALESCE (tppag_storni, ser_redd.fetchChar3Config('FONDI_ITIR_STORNI'));


and it seems to work.

tnkz a lot!

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library