В чем разница между USER() и SYS_CONTEXT ( "USERENV", "CURRENT_USER" )?

В базе данных 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'), но я не мог найти документацию по этому вопросу.

Ответ 1

Из руководства по адресу: 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 используется в хранимой процедуре или функции.

Я должен признать, что я не знаю, что означает термин "пользователь предприятия".

Btw: есть третий:

SESSION_USERID

Идентификатор пользователя базы данных при входе в систему.

Ответ 2

sys_context('USERENV', 'CURRENT_SCHEMA') - Схема, которая в настоящее время используется и как вы уже узнали, может быть изменена с помощью alter session

sys_context('USERENV', 'SESSION_USER') - Пользователь, который использовался для аутентификации во время создания сеанса и не может быть изменен

sys_context('USERENV', 'CURRENT_USER') - В значительной степени, как "session_user" устарел (по крайней мере, согласно 10g документации) < ш > (редактируется в соответствии с ответом @a_horse_with_no_name и ссылкой, которую он дал 11g docs)

sys_context('USERENV', 'AUTHENTICATED_IDENTITY') - Идентификатор, используемый для аутентификации, зависит от "AUTHENTICATION_METHOD".
из документация:

  • Аутентифицированный Kerberos корпоративный пользователь: имя пользователя kerberos
  • Внешний пользователь Kerberos: главный имя пользователя kerberos; одна и та же как имя схемы
  • Пользователь, прошедший проверку подлинности SSL: DN в пользовательский сертификат PKI
  • Внешний пользователь, прошедший проверку подлинности SSL: DN в пользовательский сертификат PKI
  • Пользователь, прошедший проверку подлинности с помощью пароля: ник; так же как и имя входа
  • Пользователь базы данных, прошедший проверку пароля: имя пользователя базы данных; так же, как имя схемы
  • OS аутентификация внешний пользователь: имя пользователя внешней операционной системы
  • Внешний пользователь с внешней идентификацией Radius/DCE: имя схемы
  • Прокси с DN: DN сервера интернет-офисов Oracle
  • Прокси с сертификатом: DN сертификата клиента
  • Прокси с именем пользователя: имя пользователя базы данных если клиент является пользователем локальной базы данных; ник, если клиент является корпоративного пользователя.
  • SYSDBA/SYSOPER с использованием файла паролей: имя пользователя
  • SYSDBA/SYSOPER с использованием аутентификации ОС: имя пользователя операционной системы

user pseudo column - Я не уверен, согласно документации, я думаю, что это как CURRENT_SCHEMA, но, по-видимому, это похоже на CURRENT_USER

Ответ 3

CURRENT_SCHEMA - это схема, которая будет приниматься, если вы назовете объект без указания его владельца. Например, если мой CURRENT_SCHEMA равен SCOTT, то SELECT * FROM EMP совпадает с SELECT * 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 завершится с ошибкой.

Ответ 4

Существует также разница в производительности между пользователем и использованием 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

Ответ 5

При использовании функции USER из PL/SQL необходимо учитывать одно важное замечание. Как я описал в этом посте, STANDARD.USER() реализован следующим образом:

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

Таким образом, он делегирует оценку user в механизме SQL, что приводит к скрытому переключению контекста PL/SQL в SQL. Если вы делаете это слишком часто, например, из-за триггера, то это может оказаться весьма вредным для производственной системы. Старайтесь избегать вызова USER() из PL/SQL и используйте sys_context('USERENV', 'SESSION_USER').