Se você estiver usando um banco de dados 11g, poderá usar o
DBMS_XA pacote
para permitir que uma sessão se junte a uma transação iniciada pela primeira sessão. Como demonstra Tim Hall, você pode iniciar uma transação em uma sessão, ingressar nessa transação de outra sessão e ler as alterações não confirmadas feitas na transação. Infelizmente, no entanto, isso não vai ajudar com variáveis de sessão (assumindo que "variável de sessão" significa variável de pacote que tem escopo de sessão). Crie o pacote e a tabela:
CREATE TABLE foo( col1 NUMBER );
create or replace package pkg_foo
as
g_var number;
procedure set_var( p_in number );
end;
create or replace package body pkg_foo
as
procedure set_var( p_in number )
as
begin
g_var := p_in;
end;
end;
Na Sessão 1, iniciamos uma transação global, definimos a variável de pacote e inserimos uma linha na tabela antes de suspender a transação global (o que permite que outra sessão a retome)
SQL> ed
Wrote file afiedt.buf
1 declare
2 l_xid dbms_xa_xid := dbms_xa_xid( 1 );
3 l_ret integer;
4 begin
5 l_ret := dbms_xa.xa_start( l_xid, dbms_xa.tmnoflags );
6 pkg_foo.set_var(42);
7 dbms_output.put_line( 'Set pkg_foo.g_var to ' || pkg_foo.g_var );
8 insert into foo values( 42 );
9 l_ret := dbms_xa.xa_end( l_xid, dbms_xa.tmsuspend );
10* end;
SQL> /
Set pkg_foo.g_var to 42
PL/SQL procedure successfully completed.
Na sessão 2, retomamos a transação global, lemos a tabela, lemos a variável de sessão e encerramos a transação global. Observe que a consulta na tabela vê a linha que inserimos, mas a alteração da variável do pacote não é visível.
SQL> ed
Wrote file afiedt.buf
1 declare
2 l_xid dbms_xa_xid := dbms_xa_xid( 1 );
3 l_ret integer;
4 l_col1 integer;
5 begin
6 l_ret := dbms_xa.xa_start( l_xid, dbms_xa.tmresume );
7 dbms_output.put_line( 'Read pkg_foo.g_var as ' || pkg_foo.g_var );
8 select col1 into l_col1 from foo;
9 dbms_output.put_line( 'Read COL1 from FOO as ' || l_col1 );
10 l_ret := dbms_xa.xa_end( l_xid, dbms_xa.tmsuccess );
11* end;
SQL> /
Read pkg_foo.g_var as
Read COL1 from FOO as 42
PL/SQL procedure successfully completed.
Para compartilhar o estado da sessão entre as sessões, seria possível usar um contexto global do aplicativo em vez de usar variáveis de pacote? Você pode combinar isso com o
DBMS_XA
pacotes se você quiser ler as tabelas do banco de dados e o estado da sessão. Crie o contexto e o pacote com o getter e o setter
CREATE CONTEXT my_context
USING pkg_foo
ACCESSED GLOBALLY;
create or replace package pkg_foo
as
procedure set_var( p_session_id in number,
p_in in number );
function get_var( p_session_id in number )
return number;
end;
create or replace package body pkg_foo
as
procedure set_var( p_session_id in number,
p_in in number )
as
begin
dbms_session.set_identifier( p_session_id );
dbms_session.set_context( 'MY_CONTEXT', 'G_VAR', p_in, null, p_session_id );
end;
function get_var( p_session_id in number )
return number
is
begin
dbms_session.set_identifier( p_session_id );
return sys_context('MY_CONTEXT', 'G_VAR');
end;
end;
Na sessão 1, defina o valor da variável de contexto
G_VAR
para 47 para a sessão 12345 begin
pkg_foo.set_var( 12345, 47 );
end;
Agora, a sessão 2 pode ler o valor do contexto
1* select pkg_foo.get_var( 12345 ) from dual
SQL> /
PKG_FOO.GET_VAR(12345)
----------------------
47