Skip to Main Content
  • Questions
  • Global variable across different sessions

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, Arvind .

Asked: October 09, 2001 - 9:09 am UTC

Last updated: May 01, 2016 - 10:58 am UTC

Version: 8.1.7

Viewed 50K+ times! This question is

You Asked

Hi Tom,
I have a very small problem. Can we store any value using plsql package in the manner that it should be same for all sessions using that package and if any session changes that value then it should become the new value for that variable for all sessions.? Or in other words same like Static variable in Java for a class's different objects.
Thanks in advance
Arvind Kapil

and Tom said...

Well, thats not like a static variable in a java program -- the analogy would be that if I changed a static variabe in java -- every program running out there would see the same value!

PLSQL, just like java, runs in a VM. Every user runs their own copy. A PLSQL global is just like a Java global in this regards. Every package (class) that access it in the same session ( process) will see the same value.

So, plsql and java are alike in this case.

Your solution will be to use a database table:

create table global_value ( x int );
insert into global_value values ( 0 );


create or replace package get_global
as
function val return number;
procedure set_val( p_x in number );
end;
/

create or replace package body get_global
as

function val return number
as
l_x number;
begin
select x into l_x from global;
return l_x;
end;

procedure set_val( p_x in number )
as
pragma autonomous_transaction;
begin
update global set x = p_x;
commit;
end;

end;
/



You need the locking and concucrrency controls afforded by the database, you need to use the database to share the information.





Rating

  (31 ratings)

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

Comments

A reader, October 09, 2001 - 11:02 am UTC

Kinldy elucidate the following

"PLSQL, just like java, runs in a VM. "

Thank you

Tom Kyte
October 09, 2001 - 3:10 pm UTC

Do you understand how java runs? In a VM (virtual machine). Well, PLSQL does exactly the same. there is a virtual machine that runs the code.

PLSQL is compiled to pcode (byte code) and run by an interpreter that pretends to be an operating system.

Java is compiled to byte code (pcode) and .....

Its the same thing. for the same reason that java is portable -- PLSQL is portable. The same plsql runs on an OS/390 mainframe as does on my windows laptop as does on my Unix system. Oracle ported the plsql VM so you don't have to port your code.

Only solution?

Arvind, October 09, 2001 - 3:26 pm UTC

Is this the only solution of my problem ? No other way

Tom Kyte
October 09, 2001 - 3:35 pm UTC

In order to get a "super global variable" as you would like -- you would use a database table.

Think about it -- its a pretty hard problem. What would your solution in Java be if all of your java processes needed to access the same variable -- you'd have to write some OS dependent stuff and use shared memory, a memory mapped file or an OS file.

The database table is actually a very elegant solution as it does all of the concurrency control and such for you. The amount of code you have to write for such a functionality is very small.

is it possible...

Alvin, June 03, 2003 - 5:31 am UTC

if i create a package....

---
CREATE OR REPLACE PACKAGE BODY DUMMY
AS
G_VAR NUMBER := 10 ;
BEGIN
NULL;
END;
---

would i be able to pry out the value (10 or any current value) of G_VAR on regular sql?

I'm asking this because of the procedure crypt_pkg.setkey('xxxx1111') in the dbms_obfuscation_toolkit section of your book stores the data on a global variable.



Tom Kyte
June 03, 2003 - 7:38 am UTC

as you have it, yes of course -- it is hard coded.

as i have it, no, it is not hard coded. It is a global package body variable (accessible ONLY to the code in the package body) that is set via a "setter" function.

what about a global context (if 9i)

j., June 03, 2003 - 8:39 am UTC

would this be something to think of?

Tom Kyte
June 03, 2003 - 9:39 am UTC

to share across all sessions -- yes, that would work. They could all share a single global application context.


An example...

Kamal Kishore, June 03, 2003 - 11:35 am UTC

Hi Tom,
We have a similar requirement to have global values accesible across multiple sessions.
We are currently in the process of upgrading to 9i, and was thinking of using the global context feature to do that.
Can you provide us with a simple example to do this on 9i using global context?
Appreciate your help,
Thanks,


Tom Kyte
June 03, 2003 - 12:26 pm UTC

ops$tkyte@ORA920> create or replace context App_Ctx using My_pkg
  2  ACCESSED GLOBALLY
  3  /

Context created.

ops$tkyte@ORA920>
ops$tkyte@ORA920> create or replace package my_pkg
  2  as
  3          procedure set_ctx( p_name       in varchar2,
  4                                             p_value      in varchar2 );
  5
  6          procedure init;
  7  end;
  8  /

Package created.

ops$tkyte@ORA920>
ops$tkyte@ORA920> create or replace package body my_pkg
  2  as
  3          g_session_id number := 1234;
  4
  5          procedure init
  6          is
  7          begin
  8                  null;  -- elaboration code does it all
  9          end;
 10
 11          procedure set_ctx( p_name       in varchar2,
 12                                             p_value      in varchar2 )
 13          as
 14          begin
 15                  dbms_session.set_context
 16                  ( 'App_Ctx', p_name, p_value, NULL, g_session_id );
 17          end;
 18  begin
 19                  dbms_session.set_identifier( g_session_id );
 20  end;
 21  /

Package body created.

ops$tkyte@ORA920> pause

ops$tkyte@ORA920>
ops$tkyte@ORA920> exec my_pkg.set_ctx( 'Var1', 'Val1' );

PL/SQL procedure successfully completed.

ops$tkyte@ORA920> exec my_pkg.set_ctx( 'Var2', 'Val2' );

PL/SQL procedure successfully completed.

ops$tkyte@ORA920>
ops$tkyte@ORA920> select sys_context( 'app_ctx', 'var1' ) var1,
  2         sys_context( 'app_ctx', 'var2' ) var2
  3    from dual
  4  /

VAR1       VAR2
---------- ----------
Val1       Val2

ops$tkyte@ORA920>
ops$tkyte@ORA920> connect /
Connected.
ops$tkyte@ORA920>
ops$tkyte@ORA920> select sys_context( 'app_ctx', 'var1' ) var1,
  2         sys_context( 'app_ctx', 'var2' ) var2
  3    from dual
  4  /

VAR1       VAR2
---------- ----------


ops$tkyte@ORA920>
ops$tkyte@ORA920> exec my_pkg.init

PL/SQL procedure successfully completed.

ops$tkyte@ORA920>
ops$tkyte@ORA920> select sys_context( 'app_ctx', 'var1' ) var1,
  2         sys_context( 'app_ctx', 'var2' ) var2
  3    from dual
  4  /

VAR1       VAR2
---------- ----------
Val1       Val2

 

dbms_session.set_identifier

Robert, June 03, 2003 - 6:52 pm UTC

>>ops$tkyte@ORA920> create or replace package body my_pkg
>>2 as
>>3 g_session_id number := 1234;
.......snip
>>18 begin
>>19 dbms_session.set_identifier( g_session_id );
>>20 end;


Is g_session_id just any arbitrary number you can set ?
What if another program do the same (set_identifier) using the same value ?
Thanks


Tom Kyte
June 04, 2003 - 7:40 am UTC

g_session_id is just some arbitrary session id that all sessions that wish to shared this context must use.


I showed "another program" using the same number -- i logged out / back in -- that is "another program"

if you want to share the context, the key is 1234 in this example.

What privilege?

Kamal Kishore, June 04, 2003 - 9:44 am UTC

Hi Tom,
It seems that in order to create/drop a context a user needs the "CREATE ANY CONTEXT" and "DROP ANY CONTEXT" system privilege.
Is this the only privilege required?
Will it be considered as a security risk by our DBA's? (since the privilege says "CREATE ANY...").
Or you recommend that we ask the DBA's to create it one time for us, and then we keep using it?

Once created, can we access this context without the "CREATE ANY CONTEXT" privilege?
Thanks,


Tom Kyte
June 04, 2003 - 10:07 am UTC

I would have the DBA's or an appropriately priveleged user create it one time.

You do not need create any context to access it.

What If Same User and Different Session??

Janice, May 12, 2004 - 8:24 am UTC

What if we have one user accessing the web application with two different browser sessions? And the application itself makes use of connection pooling. How can we prevent the application from getting 'confused' as to which Global Application context to use for the one user in each of the two separate browser sessions?




Tom Kyte
May 12, 2004 - 6:39 pm UTC

session ids, each browser "session" would have its own session id.

OK

Jacob, April 05, 2005 - 1:21 pm UTC

Hi Tom,
I am not able to use the procedure
dbms_session.set_context(...).

I have the privileges
"Execute any procedure and even sysoper and sysdba privileges".
Does it require any other privilege??
Please do reply.
Bye!



Tom Kyte
April 05, 2005 - 6:44 pm UTC

no example?

to use dbms_session.set_context, you have to be in the procedure, function or package that was bound to the context when you created it:

in the following ONLY P can set the context, no one else (that is what is magic about them)

ops$tkyte@ORA9IR2> create or replace context my_ctx using p
  2  /
 
Context created.
 
ops$tkyte@ORA9IR2>
ops$tkyte@ORA9IR2> create or replace procedure p
  2  as
  3  begin
  4          dbms_session.set_context( 'my_ctx', 'x', 5 );
  5  end;
  6  /
 
Procedure created.
 
ops$tkyte@ORA9IR2>
ops$tkyte@ORA9IR2> create or replace procedure p2
  2  as
  3  begin
  4          dbms_session.set_context( 'my_ctx', 'x', 5 );
  5  end;
  6  /
 
Procedure created.
 
ops$tkyte@ORA9IR2> exec dbms_session.set_context( 'my_ctx', 'x', 5 );
BEGIN dbms_session.set_context( 'my_ctx', 'x', 5 ); END;
 
*
ERROR at line 1:
ORA-01031: insufficient privileges
ORA-06512: at "SYS.DBMS_SESSION", line 78
ORA-06512: at line 1
 
 
ops$tkyte@ORA9IR2> exec p2
BEGIN p2; END;
 
*
ERROR at line 1:
ORA-01031: insufficient privileges
ORA-06512: at "SYS.DBMS_SESSION", line 78
ORA-06512: at "OPS$TKYTE.P2", line 4
ORA-06512: at line 1
 
 
ops$tkyte@ORA9IR2> exec p
 
PL/SQL procedure successfully completed.
 

OK

Jacob, April 06, 2005 - 11:44 am UTC

Hi Tom,
Thanks for your reply.It Works fine but the attributes and their values are
not reflected in dictionary views.
What might be the reason?


SQL> create or replace context ctx1 using pro1 accessed globally
  2  /

Context created.

SQL>  create or replace procedure pro1
  2   as
  3   begin
  4   dbms_session.set_context('ctx1','gvar1',100);
  5   dbms_session.set_context('ctx1','gvar2',200);
  6  end;
  7  /

Procedure created.

SQL> exec pro1

PL/SQL procedure successfully completed.

SQL> select sys_context('ctx1','gvar1'),sys_context('ctx1','gvar2') from dual


SYS_CONTEXT('CTX1','GVAR1')
--------------------------------------------------------------------------------
SYS_CONTEXT('CTX1','GVAR2')
--------------------------------------------------------------------------------
100
200


SQL> 
SQL> select * from v$context
  2  /

no rows selected

SQL> select * from session_context
  2  /

no rows selected
 

Tom Kyte
April 06, 2005 - 2:03 pm UTC

v$globalcontext

they are in the global content.

Mark, September 23, 2005 - 9:22 am UTC

Tom, I was reading the Oracle Docs
</code> http://download-west.oracle.com/docs/cd/B10501_01/appdev.920/a96590/adgsec02.htm#1011495 <code>
on this subject and came across this line.

"Note that the SYS_CONTEXT function works much like a bind variable, but only if the SYS_CONTEXT arguments are constants."

Can you talk on this point?

Thanks.

Tom Kyte
September 23, 2005 - 8:08 pm UTC

I think it is poorly worded, what I believe they meant was:

ops$tkyte@ORA10G> select * from scott.emp where ename = sys_context( 'my_ctx', ename );
 
no rows selected


will work like a FUNCTION.....


but:

ops$tkyte@ORA10G> select * from scott.emp where ename = sys_context( 'my_ctx', 'X' );
 
no rows selected


will work like a bind - if the sys_context call returns a SINGLE value in the query, it'll be "bound", else it'll be treated much like a function would be. 

Using another user's context

Beroetz, January 10, 2007 - 5:37 am UTC

SQL> CONNECT user1/*****
Connected.

SQL> create context my_ctx using my_ctx_proc
Context created.

SQL> create or replace procedure my_ctx_proc(
2 p_name in varchar2, p_val in varchar2 )
3 as
4 begin
5 dbms_session.set_context( 'my_ctx', p_name, p_val );
6 end;
8 /
Procedure created.

SQL> exec my_ctx_proc( 'Var1', 'Val1' );
PL/SQL procedure successfully completed.

SQL> grant execute on my_ctx_proc to user2
Privileges granted.

SQL> grant execute on dbms_session to user2
Privileges granted.

SQL> CONNECT user2/*****
Connected.

SQL> exec my_ctx_proc( 'Var1', 'Val1' );
ORA-01031: insufficient privileges

So can I use a context created by another user and how?
Best regards, Beroetz


Oracle Reports Connection Pool

Nishith Pandey, February 25, 2008 - 7:46 am UTC

Hi Tom,
We are moving from decentralized databases (located at each division of the company) to a centralized database server (to be located at Company HQ), so I want to use FGAC to implement VPD to limit the users' to only view their division's rows (you also agreed for the use of FGAC for this purpose in some other thread of AskTom!). Now the scene is :

Platform :

* Oracle Database 10gR2 (Windows 2003)
* Developer 6i ( Forms 6i / Reports 6i )
* Citrix Server to host the Forms/Reports working like a Middle-tier

Application Setup :

1) An Oracle User named "JAGDB" contains all the tables and programs (stored procedures, packages, functions, etc.) with undisclosed password to the users, obviously!

2) A least privileged user named "USRLOGIN" used to connect initially to the application through a home login form (forms6i) (after connecting to the Citrix Server),

3) In this home login form, user enters her Employee Id and Password (stored in a table).

4) If the authentication is successful, the user then chooses the division in which she wants to work.

5) The form is internally connected to "JAGDB" user.

6) Division Code, Division Name, Division Address is stored in an Application Context which is used in a function F_PREDICATE. This function is used in DBMS_FGA to set the policy predicate for DML and select on all the tables. Hence in the forms, user will only be able to select/DML the rows for the division she chosen.

Now, the problem is with the Oracle Reports called from the Forms. Whenever a Report is called, a separate session is started, and all the context variables are lost !!! :(

Then I read about Global Application Context which can be shared among multiple sessions through the use of Oracle User or client_identifier or both.

But since, we are using only single Oracle user "JAGDB", and if we set client_identifier, it is also lost in new reports session just like application contexts, we are in trouble now !

We don't want to create oracle users for the employees.

Your comments on the issue is very valuable for us. Please guide us !

Waiting ur response...

Nishith Pandey, February 26, 2008 - 6:46 am UTC

Hi Tom,

I am waiting ur valuable response over above posting.

Please reply.


Tom Kyte
February 26, 2008 - 7:58 am UTC

Hah, "ur", hmmmmm...


Anyway, I haven't touched reports in over a decade. Nor forms.

Try otn.oracle.com -> discussion forums.

A reader, February 26, 2008 - 10:28 am UTC


To : Nishith Pandey from India

A reader, February 26, 2008 - 11:41 am UTC

"Division Code, Division Name, Division Address is stored in an Application Context which is used
in a function F_PREDICATE. This function is used in DBMS_FGA to set the policy predicate for DML
and select on all the tables."

1. Create user defined parameters in report
2. Pass all the context variables from form to report
3. In the before-report trigger, set all the context variables again.

If above doesn't help, please try otn.oracle.com

HTH

Security Issue

A reader, February 27, 2008 - 8:37 am UTC

Thanks for the response. I had the idea about passing parameter to the report but I don't want developers to set the context in any other form/report apart from the home login form for security reasons, because procedure to set context can be misused. In other words, I want a one-point Context Setting. If it is not possible, then how can I secure my procedure which sets the contexts so that it can only be used in the home login form?


Tom Kyte
February 27, 2008 - 11:22 am UTC

your decision to use a single user account - this "super user account" will limit your options (it is not very secure to use a single account)

as the other poster (and I) above said, you'll be best served by using otn.oracle.com and the developer forums, you can read and query about the hacks others have done in scenarios like yours.


.....
5) The form is internally connected to "JAGDB" user.
.......

that means you must be transmitting the password from the database back to forms, I sure hope you are encrypting all network traffic, else it would take someone a couple of seconds with a sqlnet.ora tweak on the client to find out this super secret.

Is Session Role helpful ?

Nishith Pandey, February 29, 2008 - 7:40 am UTC

Hi Tom,
If I create a role say "APP_ROLE" and grant all required privileges of "JAGDB" to that role and then create another oracle user say "JAGUSR" with only connect privilege and with "APP_ROLE" granted but not default. With this setup, the home login form will be connected with "JAGUSR" and enable the role via dbms_session.set_role. Will this be a better security?

(Again when the reports (6i) session is spawned from calling form (6i), role is no longer set just like the contexts are reset).


Tom Kyte
March 01, 2008 - 10:34 am UTC

you missed the bit where I said I'd get your password in about 5 seconds.....

and the bit about otn, since I basically haven't touched forms and reports since 1995...

Nishith Pandey, March 03, 2008 - 2:46 am UTC

Hi Tom,

I didn't miss what u said about hacking password..That's why in my posting above, I asked your feedback about a least privileged oracle user to let the user connect with the home login form. And I also followed up OTN for forms/reports query. Thanks for that very right forum refernence.

Could you please also let me know how the password can be hacked through sqlnet.ora tweak as you mentioned above as it is quite interesting to know and to enhance the conceptual knowledge of oracle further.
Tom Kyte
March 03, 2008 - 7:10 am UTC

when did "U" become involved in this, I really want to meet "U" - very popular person.

Using the least privileged user doesn't change anything. You are a) storing the password in the database somewhere, b) sending it back over the network, c) logging in using forms (do you know in forms how easy it is for an end user to submit ad-hoc SQL to the database? Once you log in as this 'super duper user', I can use forms to do SQL you did not anticipate me to - usually, when used normally - this is not an issue with forms at all, since the user logs in as themselves - NORMALLY - but since you are logging in as a super user, this is a problem to consider).

using the sqlnet.ora, which all I need is the ability to create one anywhere in the file system (which I can do, because I'm logged into some account there). Then, I can set my tns_admin environment variable to point to where it is, so your forms application will use mine instead of the one you think it should. Then, I'll run your form from the command line (using my environment). My sqlnet.ora will have a trace setting on that will dump all network packets.

So, since you send the password back, I'll see it in the trace.

Unless you use encryption of course.

Sorry for "U"

Nishith Pandey, March 07, 2008 - 5:56 am UTC

Hi Tom

I am sorry for "U". I pay special attention to write posts on Asktom regarding "U", "UR", etc. I am in habit of these because of Mobile SMS messages I do in abbreviated terms.

What trace settings we need to set in SQLNET.ORA in order for the packets log ?
Tom Kyte
March 10, 2008 - 10:04 am UTC

... I am in habit of these because of Mobile SMS messages I do in
abbreviated terms.
...

stop doing it there too then! When I get a TXT from an *adult* using that stuff - I immediately think "12"

As is, they are 12 years old. Not a good impression.
Not at all.

And many people feel that way - and might not say anything.


http://www.oracle.com/pls/db102/search?remark=advanced_search&word=sqlnet.ora+trace&format=ranked&book=&preference=

variables in packages

AMIR RIAZ, March 10, 2008 - 2:46 pm UTC

hi tom

my understand about variables was that most variable are created in PGA. but recently a read a book by steven in which he said that in case of

Pragma SERIALLY_REUSABLE

variables are created in SGA. what is your opinion?. The argument he puts is that when a procedure is finish it gives that area (i think sql area or plsql area) back. I am finding hard to believe it.

my theory is in case of SERIALLY_REUSABLE the variable are created in stack which otherwise should be created in heap. normal packages without SERIALLY_REUSABLE clause, the variables inside the packages are created in heap. which one is right?

regards
Amir Riaz
Tom Kyte
March 10, 2008 - 2:57 pm UTC

there are no "opinions" here - just the way things work.

Ok, there is this "pragma serially reusable" - what that means is when you touch a package in a given CALL (a single trip to the server, each session typically consists of hundred or thousands of calls, indeed each each transaction typically does...) the package is instantiated

At the end of the call, it is deinstantiated.

It does "give everything back", it is designed for applications that do not need to maintain a state.

The documentation:
http://docs.oracle.com/docs/cd/B19306_01/appdev.102/b14261/seriallyreusable_pragma.htm#LNPLS01346

is fairly clear:

... The global memory for serially reusable packages is pooled in the System Global Area (SGA), not allocated to individual users in the User Global Area (UGA). That way, the package work area can be reused. When the call to the server ends, the memory is returned to the pool. Each time the package is reused, its public variables are initialized to their default values or to NULL. ....

so, yes, in the case of serially_reusable - the package variables (since they need not stick around) are allocated there and reused by the next session.


And since it is so rare to see serially_reusable (I have yet to see it used in real life...), it is sort of a non-issue...

Reinitialize

Andrew Markiewicz, December 23, 2009 - 5:25 pm UTC

Tom

The documentation for serially reusable states:
http://download.oracle.com/docs/cd/B14117_01/appdev.101/b10795/adfns_pc.htm#1008314
"
A package that is marked SERIALLY_REUSABLE has the following properties:

...

* A pool of package instantiations is kept, and whenever a "unit of work" needs this package, one of the instantiations is "reused", as follows:
o The package variables are reinitialized (for example, if the package variables have default values, then those values are reinitialized).
o The initialization code in the package body is run again.
* At the "end work" boundary, cleanup is done.
o If any cursors were left open, then they are silently closed.
o Some non-reusable secondary memory is freed (such as memory for collection variables or long VARCHAR2s).
o This package instantiation is returned back to the pool of reusable instantiations kept for this package.
"

Are there any more details about how this is performed? I am asking because we have a need to reinitialize specific packages. There does not seem to be an explicit mechanism to do this, but it seems SERIALLY REUSABLE does just that and I would like access to that.

Any pointers would be appreciated.
Thanks.
Andrew
Tom Kyte
December 31, 2009 - 2:26 pm UTC

basically - the package is re-initialized for every CALL to the database from the client.


In my opinion, if you have this need:

... I am asking because we have a need to reinitialize specific packages ...

you are barking up the wrong tree with serially reusable. If after each call by a client to the database the package should re-initialize itself (reset all GLOBALS back to their defaults)... Then that package should HAVE NO GLOBALS.

If you just do not use globals - you don't have a state to worry about, you wouldn't have to think about it.

The only time you should use globals is when you NEED THEM and apparently, you explicitly DO NOT need, in fact you explicitly DO NOT WANT them.

If you do not have any variables defined outside of a function or procedure, you do not need to re-initialize anything - that would be my suggestion.

Global App Context not available in RAC?

Pasko, January 02, 2010 - 10:31 am UTC

Hi Tom,

Happy New Year!
Global Application contexts are really cool, but i read in the Docs that this feature can not be used for RAC, at least until 10GR2..do you know if it is now possible to use this Feature in RAC for 11GR2 ?

Regards,

Pasko

Reinitialize

Andrew Markiewicz, January 07, 2010 - 3:17 pm UTC

I agree that serially_reusable is not what we need. I was interested in how serially_reusable was achieving it's objective in order to see if I could exploit the ability to reinitialize a package on request.

As for the "need" to this, it is an attempt at making lemonade when given limes... or something like that.

We are writing an application and the programmer writing the core of the application made extensive and abusive use of package globals. i.e. Package variables in the spec are accessed and set by essentially any code that has access to it. The result is an enormous bowl of pasta. Since it was difficult to know what was going on with the variables, he decided he needed to guarantee he had a clean slate when starting a new user transaction (since some other process might have changed the package variables). He wanted to be able to reinitialize the specific packages he was working with but that ability does not exist.
The solution he used was a call to DBMS_SESSION.MODIFY_PACKAGE_STATE(DBMS_SESSION.REINITIALIZE).

That unfortunately has the effect of wiping out all package variables, global temporary tables and open/cached cursors in the session. Needless to say this app does not play well nicely with other apps that are expecting to retain package state and causes elusive, hair thinning bugs.

You would think the answer to this issue would be to rewrite the offending app to ensure it only wipes out the variables it needs to. But the prescribed answer is to have the other applications save their package state in the event this other application wipes it out.

After several unsuccessful attempts at reasoning that solution, I was just looking for a way to just reinitialize specific packages so that other apps would not be at the mercy of this one. Any ideas toward that goal would be greatly appreciated.
Thanks.


Tom Kyte
January 11, 2010 - 8:44 pm UTC

... We are writing an application and the programmer writing the core of the
application made extensive and abusive use of package globals. ...

that means you are writing the application (it is not done) and you can still fire the guy.


... But the prescribed
answer is to have the other applications save their package state in the event
this other application wipes it out.
...

I do not do this often, nor lightly. But I would be willing to have a con call with you and the management that would be able to institute a change and tell them how bad this is. My email is well known.


Reinitialize

Andrew Markiewicz, January 18, 2010 - 1:09 pm UTC

Tom,
Thank you for the generous offer for a con call but I don't know if that would help the situation at this moment. We have discussed several times the ramifications of this technique but the project deadline is approaching and changing that part of the code is apparently too volatile a modification at this time. There is talk of fixing it post-implementation, but that does not help alleviate the extra and needless coding in other applications, not to mention any lurking issues that may not have been found. But the issues have been brought to attention and will be addressed.

Thank you again for your offer and for your assistance in fortifying my position on the matter.

Andrew
Tom Kyte
January 19, 2010 - 3:56 pm UTC

nice, an utterly incompetent piece of code - that is so fragile people are afraid to touch it - is going to go production to meet a deadline.

this will work well.

good luck.

When Global Application Context values expire?

Parthiban Nagarajan, January 21, 2010 - 9:50 am UTC

Hi Tom

You recommended to employ a table to store the SESSION_ID (=> Context identifier) and after a specified period of time, a job which would remove the context entries by taking the last accessed time from that table ...

But, I want to know whether Oracle will remove the entries automagically after a specified interval ... ?

When? and is it configurable?

Thanks in Advance ... ;)
Tom Kyte
January 21, 2010 - 10:45 am UTC

no, it won't. we don't know when you might be done with it.

well, ok, maybe a shutdown will do it automagically for you - but it really isn't the same :)

Resetting global variable in same session.

Snehasish Das, February 18, 2011 - 7:50 am UTC


Hi Tom,

I have a problem with package global variable. If I am calling the same package in the same session twice, its using the old value of the global variable (initialised value) and not useing the modified one which I want to use.

Please note the actual code is OWB generated and the below code is only for simulation process so please ignore the coding standar.

create or replace package body pack_abc
as
procedure proc_display1
is
v_edw_date date;
begin
for i in 1..5
loop
dbms_output.put_line ('FIRST PACK'||v_name);
dbms_output.put_line ('DATE_VALUE::'||v_date);
insert into x_test_date_key values (v_date);
update x_test_date set edw_date = sysdate + i;
commit;
select edw_date into v_edw_date from x_test_date;
dbms_output.put_line('NEW_DATE:::'||v_edw_date);
end loop;
end;
END;

create or replace function FN_GET_CSS_WK_END_DT return number is
Result_1 number;
begin
select date_time_key into result_1 from dm_date_time where date_time = (select trunc(lookup_date) from x_test_date);
return(Result_1);
end FN_GET_CSS_WK_END_DT;


set serverout on;
begin
dbms_output.put_line(pack_abc.v_name);
pack_abc.proc_display1;
--DBMS_SESSION.RESET_PACKAGE;
dbms_output.put_line(pack_abc.v_name);
pack_abc.proc_display1;
end;
/


TOM_ORACLE_GURU
FIRST PACKTOM_ORACLE_GURU
DATE_VALUE::7635
NEW_DATE:::19-02-2011
FIRST PACKTOM_ORACLE_GURU
DATE_VALUE::7635
NEW_DATE:::20-02-2011
FIRST PACKTOM_ORACLE_GURU
DATE_VALUE::7635
NEW_DATE:::21-02-2011
FIRST PACKTOM_ORACLE_GURU
DATE_VALUE::7635
NEW_DATE:::22-02-2011
FIRST PACKTOM_ORACLE_GURU
DATE_VALUE::7635
NEW_DATE:::23-02-2011
TOM_ORACLE_GURU
FIRST PACKTOM_ORACLE_GURU
DATE_VALUE::7635
NEW_DATE:::19-02-2011
FIRST PACKTOM_ORACLE_GURU
DATE_VALUE::7635
NEW_DATE:::20-02-2011
FIRST PACKTOM_ORACLE_GURU
DATE_VALUE::7635
NEW_DATE:::21-02-2011
FIRST PACKTOM_ORACLE_GURU
DATE_VALUE::7635
NEW_DATE:::22-02-2011
FIRST PACKTOM_ORACLE_GURU
DATE_VALUE::7635
NEW_DATE:::23-02-2011

Can you please let me know what needs to be done so that the package global variable is reset for each run.

Regards,
Snehasish Das.

Tom Kyte
February 18, 2011 - 9:27 am UTC

options:

o make an assignment to it - set it yourself
o use the dbms_session.reset_package like this:

ops$tkyte%ORA11GR2> create or replace package my_pkg
  2  as
  3          g_global varchar2(20) := 'hello';
  4  end;
  5  /

Package created.

ops$tkyte%ORA11GR2> 
ops$tkyte%ORA11GR2> begin
  2          my_pkg.g_global := 'world';
  3          dbms_output.put_line( my_pkg.g_global );
  4  end;
  5  /
world

PL/SQL procedure successfully completed.

ops$tkyte%ORA11GR2> exec    dbms_session.reset_package;

PL/SQL procedure successfully completed.

ops$tkyte%ORA11GR2> set serveroutput on
ops$tkyte%ORA11GR2> begin
  2          dbms_output.put_line( my_pkg.g_global );
  3  end;
  4  /
hello

PL/SQL procedure successfully completed.


o disconnect and reconnect after each "run"



Otherwise - it is working exactly as designed - globals are intended by design to retain their values for the life of the session.

Resetting the package global variable

Snehasish Das, February 18, 2011 - 7:58 am UTC

Hi Tom,

Apologies I forgot to add the package spec.

Please find the spec below.

create or replace package pack_abc
as
procedure proc_display1;
v_name varchar2(100) := 'MINTAX_THE_BOND';
v_date number := FN_GET_CSS_WK_END_DT;
end;

many thanks,

Snehasish Das.

question regarding using a global variable

Raj, December 12, 2012 - 7:04 pm UTC

I have a similar kind of problem .. to use s global variable to store exception value.

My question is :

If I declare a variable in spec of a package 1
and use it in different packages which i call from 1.

will this be session specific?
Tom Kyte
December 17, 2012 - 3:38 pm UTC

... to use s global variable to store exception
value. ...

I have a feeling I'd not like your code very much - there should be no reason to do that - you just let them propagate if you cannot fix them.



global variables in packages are session private, yes, just as you would expect (they would be useless otherwise!)

Package vs context variable

Michel Cadot, December 18, 2012 - 4:36 am UTC


Depending on the kind of variable (complex or simple) and its usage (specific to some treatment/package or not), I'd use a context variable instead of a package one.

Regards
Michel

About oracle sql

Naheshkumar, April 29, 2016 - 6:11 am UTC

Sir, what is the scope of global variable in oracle sql.please send your response to maheshkumaritagi@gmail.com.
Connor McDonald
May 01, 2016 - 10:58 am UTC

a "global variable" (ie, in a package spec) can be seen by anything *in that session*.

If you want something to span *all* sessions, use a table or a global context variable.

https://docs.oracle.com/cd/B28359_01/network.111/b28531/app_context.htm


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