我会使用上下文而不是向每个存储过程调用传递额外的参数。上下文是存储存储过程都可以引用的任意会话级状态数据的方便位置。
例如,我可以为我的应用程序创建一个上下文 MYAPP_CTX 并创建一个简单的包,让我可以在上下文中设置我想要的任何值。
SQL> create context myapp_ctx using ctx_pkg;
Context created.
SQL> create package ctx_pkg
2 as
3 procedure set_value( p_key in varchar2, p_value in varchar2 );
4 end;
5 /
Package created.
SQL> create package body ctx_pkg
2 as
3 procedure set_value( p_key in varchar2, p_value in varchar2 )
4 as
5 begin
6 dbms_session.set_context( 'MYAPP_CTX', p_key, p_value );
7 end;
8 end;
9 /
Package body created.
当应用程序从连接池中获得连接时,它会简单地设置所有上下文信息一次。
SQL> begin
2 ctx_pkg.set_value( 'USERNAME', 'JCAVE' );
3 ctx_pkg.set_value( 'IP_ADDRESS', '192.168.17.34' );
4 end;
5 /
PL/SQL procedure successfully completed.
同一会话中的后续调用和查询可以只询问存储在上下文中的任何值。
SQL> select sys_context( 'MYAPP_CTX', 'USERNAME' )
2 from dual;
SYS_CONTEXT('MYAPP_CTX','USERNAME')
--------------------------------------------------------------------------------
JCAVE
实际上,您几乎肯定希望将clear_context 过程添加到调用dbms_session.clear_context( 'MYAPP_CTX' ) 的包中,以在将连接返回到连接池时清除上下文中设置的任何值,以避免无意中允许上下文来自一个会话的信息会渗透到另一个会话中。您可能还会使用单独的程序来设计包,以设置和获取至少公共密钥(用户名、IP 地址等),而不是在多个位置硬编码“用户名”。为了简单起见,我使用了一个通用的 set_value 方法。