В чем разница между 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')
.