Si está usando una base de datos 11g, podría usar el DBMS_XA
paquete
para permitir que una sesión se una a una transacción iniciada por la primera sesión. Como demuestra Tim Hall, puede iniciar una transacción en una sesión, unirse a esa transacción desde otra sesión y leer los cambios no confirmados realizados en la transacción. Desafortunadamente, sin embargo, eso no va a ayudar con las variables de sesión (asumiendo que "variable de sesión" significa variable de paquete que tiene alcance de sesión).
Cree el paquete y la tabla:
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;
En la Sesión 1, comenzamos una transacción global, configuramos la variable del paquete e insertamos una fila en la tabla antes de suspender la transacción global (lo que permite que otra sesión la reanude)
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.
En la sesión 2, reanudamos la transacción global, leemos de la tabla, leemos la variable de sesión y finalizamos la transacción global. Tenga en cuenta que la consulta contra la tabla ve la fila que insertamos pero el cambio de variable del paquete no es visible.
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 compartir el estado de la sesión entre las sesiones, ¿sería posible usar un contexto de aplicación global
en lugar de usar variables de paquete? Podrías combinar eso con el DBMS_XA
paquetes si desea leer tanto las tablas de la base de datos como el estado de la sesión.
Cree el contexto y el paquete con getter y 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;
En la sesión 1, establezca el valor de la variable de contexto G_VAR
a 47 para la sesión 12345
begin
pkg_foo.set_var( 12345, 47 );
end;
Ahora, la sesión 2 puede leer el valor del contexto
1* select pkg_foo.get_var( 12345 ) from dual
SQL> /
PKG_FOO.GET_VAR(12345)
----------------------
47