0defb3aa

Это старое решение, которое давно


Это старое решение, которое давно практикуется в поставках Oracle для организации удобного доступа к таблицам словаря-справочника. В самом деле, известно, что каждый пользователь Oracle, даже при наличии у него всего-навсего привилегии CREATE SESSION, имеет возможность обратиться к примеру, к таблице USER_TABLES, чтобы посмотреть список своих собственных таблиц. Каждый пользователь обращается к одной и той же таблице (USER_TABLES), но видит в ней только свои данные.
Строго говоря, в прозвучавшей только что формулировке кроется подлог: реально USER_TABLES – это выводимая таблица (view) в схеме SYS, в определении которой присутствует ссылка на имя текущего пользователя, и для которой создан одноименный публичный (PUBLIC, то есть общедоступный) синоним. От этого-то синонима, для которого не требуется уточнения имени владельца (согласно общему правилу ссылки на небольшое количество «общесистемных» объектов, не принадлежащих никакой одной схеме), и разворачивается запрос к реальным таблицам словаря-справочника при обращении конкретного пользователя Oracle к USER_TABLES.
Как эта механика оформлена, желающие могут подсмотреть в файле-сценарии $ORACLE_HOME/rdbms/admin/catalog.sql. Он запускается (автоматически, вручную ли) при заведении базы данных почти любой конфигурации (за исключением вариантов typical и наиболее типичных в версии 10, где БД заводится не прогоном команд SQL, а копированием готовых образов с установочного клмплекта дисков). Для нашего примера эта механика будет выглядеть так.
Зайдем для начала в систему от имени SYS и заведем пользователя ALLEN:
CONNECT / AS SYSDBA (в версиях 8, 7 лучше CONNECT INTERNAL)
CREATE USER ALLEN IDENTIFIED BY ALLEN;
GRANT CREATE SESSION TO ALLEN;
Тут же, заодно, выдадим право пользователю SCOTT создавать публичные синонимы, так как изначально этого права у него нет:
GRANT CREATE PUBLIC SYNONYM TO SCOTT;
Теперь войдем как SCOTT:
CONNECT scott/tiger
CREATE VIEW emps AS SELECT * FROM emp WHERE deptno = (SELECT deptno FROM emp WHERE ename = USER);


CREATE PUBLIC SYNONYM emps FOR emps;
GRANT SELECT ON emps TO allen;
А теперь проверка:
SQL> SELECT ename FROM emps;
ENAME



----------

SMITH

JONES

SCOTT

ADAMS

FORD

5 rows selected.
А вот, что увидит ALLEN:
SQL> CONNECT allen/allen
SQL> SELECT ename FROM emps;
ENAME

----------

ALLEN

WARD

MARTIN

BLAKE

TURNER

JAMES
6 rows selected.
Замечание. При создании выводимой таблицы EMPS молчаливо подразумевалось, что в EMP имя сотрудника уникально. В существующих данных это действительно так, но в описании таблицы это обстоятельство никак не обозначено, так что при обращение к EMPS при других данных мы рискуем получить ошибку. Здесь мы закрываем на это глаза, но в промышленных системах к формулировке схемы (таблиц базовых и выводимых) нужно подходить более тщательно: в нашем случае или сделать поле EMP.ENAME уникальным, или же заменить формулировку EMPS, убрав оттуда вложенный запрос и применив соединение.

Содержание раздела