USER()和SYS_CONTEXT('USERENV','CURRENT_USER')有什么区别?

时间:2012-06-12 18:37:59

标签: oracle plsql oracle10g oracle11g

在Oracle数据库中,以下内容之间存在以下差异:

  • 用户()
  • sys_context('USERENV','CURRENT_USER')
  • sys_context('USERENV','SESSION_USER')

这些也可能是“当前用户”的相关值吗?

  • sys_context('USERENV','CURRENT_SCHEMA')
  • sys_context('USERENV','AUTHENTICATED_IDENTITY')

我特别感兴趣的是哪些可以更改,哪些可以更改它们,哪些不能更改值,哪些具有基于连接类型的不同值,以及哪些(始终)是用于的模式登录数据库。

在我的大部分测试中,值始终相同。唯一的例外是运行以下内容以更改'CURRENT_SCHEMA':

alter session set current_schema=<SCHEMA>

执行以下操作会导致错误:

alter session set current_user=<USER> --even as sys/system, which is good I suppose

因此,所有这些都存在某种安全/规则。但是,拥有SESSION_USER和CURRENT_USER背后一定有一些原因。我还假设user()可以是sys_context的快捷方式('USERENV','CURRENT_USER'),但我找不到有关此问题的文档。

5 个答案:

答案 0 :(得分:15)

来自手册:http://docs.oracle.com/cd/E11882_01/server.112/e26088/functions184.htm#SQLRF51825

CURRENT_USER

  

其权限当前处于活动状态的数据库用户的名称。这可能会在会话期间发生变化,以反映任何活动定义者权限对象的所有者。当没有定义者的权限对象处于活动状态时,CURRENT_USER返回与SESSION_USER相同的值。当直接在视图定义的主体中使用时,这将返回正在执行使用视图的游标的用户;它不会将游标中使用的视图视为定义者的权利。

SESSION_USER

  

登录时数据库用户的名称。对于企业用户,返回架构。对于其他用户,返回数据库用户名。该值在整个会话期间保持不变。

因此 SESSION_USER和CURRENT_USER之间的区别,尤其是在存储过程或函数中使用CURRENT_USER时。

我不得不承认我不知道“企业用户”这个词的意思。

顺便问一下:还有第三个:

SESSION_USERID

  

登录时数据库用户的标识符。

答案 1 :(得分:3)

sys_context('USERENV', 'CURRENT_SCHEMA') - 可以使用alter session

更改当前正在使用的模式以及您已发现的模式

sys_context('USERENV', 'SESSION_USER') - 在创建会话期间用于身份验证且无法更改的用户

sys_context('USERENV', 'CURRENT_USER') - 非常类似于“session_user”已弃用(至少根据10g documentation
(根据@ a_horse_with_no_name的答案以及他给11g docs的参考文件进行编辑)

sys_context('USERENV', 'AUTHENTICATED_IDENTITY') - 用于身份验证的身份取决于“AUTHENTICATION_METHOD”。
来自documentation

  
      
  • 经过Kerberos身份验证的企业用户:kerberos主要名称
  •   
  • Kerberos认证的外部用户:kerberos主要名称;相同   作为模式名称
  •   
  • 经过SSL身份验证的企业用户:中的DN   用户的PKI证书
  •   
  • SSL认证的外部用户:中的DN   用户的PKI证书
  •   
  • 经过密码验证的企业用户:   昵称;与登录名相同
  •   
  • 经过密码验证的数据库用户:   数据库用户名;与架构名称相同
  •   
  • OS-认证   外部用户:外部操作系统用户名
  •   
  • Radius / DCE认证的外部用户:架构名称
  •   
  • 使用DN的代理   :客户端的Oracle Internet Directory DN
  •   
  • 证书代理:   客户的证书DN
  •   
  • 使用用户名的代理:数据库用户名   如果客户端是本地数据库用户;昵称,如果客户是一个   企业用户。
  •   
  • SYSDBA / SYSOPER使用密码文件:登录名
  •   
  • 使用OS身份验证的SYSDBA / SYSOPER:操作系统用户名
  •   

user pseudo column - 我不确定,根据文档,我认为它就像CURRENT_SCHEMA,但显然它就像CURRENT_USER

答案 2 :(得分:1)

CURRENT_SCHEMA是在未指定对象的情况下命名对象时将采用的架构。例如,如果我的CURRENT_SCHEMASCOTT,则SELECT * FROM EMPSELECT * FROM SCOTT.EMP相同。默认情况下,当我第一次连接到Oracle时,CURRENT_SCHEMA与CURRENT_USER相同。

但是,如果我以SCOTT身份连接,我可以发出ALTER SESSION SET CURRENT_SCHEMA=JOE,然后当我SELECT * FROM EMP时,它会被解释为JOE.EMP而不是SCOTT.EMP }。当然,如果我SELECT上没有JOE.EMP权限,或者JOE没有名为EMP的对象,则SELECT会失败

答案 3 :(得分:1)

使用PL / SQL中的USER函数时,有一个重要注意事项要考虑。由于我拥有documented in this blog postSTANDARD.USER()的实现方式如下:

function USER return varchar2 is
c varchar2(255);
begin
    select user into c from sys.dual;
    return c;
end;

因此,它委派了对SQL引擎中的user进行评估,这导致了从PL / SQL到SQL上下文的隐藏切换。如果您经常这样做,例如从触发器之内开始,那么在生产系统中可能会造成相当大的伤害。尝试避免从PL / SQL调用USER(),而改用sys_context('USERENV', 'SESSION_USER')

答案 4 :(得分:0)

USER和使用sys_context之间也存在性能差异

declare 
  v_result varchar2(100);
begin
  for i in 1..1000000 loop
  v_result := sys_context('userenv','session_user');
  end loop;
end;
/

-- 2.5s

declare 
  v_result varchar2(100);
begin
  for i in 1..1000000 loop
  v_result := user;
  end loop;
end;
/ 

-- 47s

另请参阅 https://svenweller.wordpress.com/2016/02/24/sequence-and-audit-columns-with-apex-5-and-12c/http://www.grassroots-oracle.com/2019/01/oracle-user-vs-sys-context.html