2017-01-20 7 views
0

я таблица типа объекта определяется как этотМожет ли «таблица типа» манипулировать в PL/SQL?

create type user_role_ty as object (
    username   varchar2(32), 
    role_nam   varchar2(32) 
); 
create type user_role_nt as table of user_role_ty 
/

И выходной переменной в функции

p_user_role_list out bt_ww_user_role_nt 

После заполнения

select user_role_ty (username, role_nam) 
    bulk collect into p_user_role_list 
(...) 

Как я могу изменить эту переменную типа таблицы? Я хотел бы удалить некоторые строки, например. главный администратор может видеть все, локальный администратор не должен видеть основные админов, пользователь может видеть себя только т.д. Укороченный:

if is_vendor(...) then 
    NULL; 
elsif is_admin(...) then 
    delete from p_user_role_list 
    where username in ((...) user_name_list); 
else 
    delete from p_user_role_list 
    where username <> p_username; 

Просто не работает. Существует несколько возможностей: ни один из них не является простым:

  • Используйте копию-вставку того же идентичного оригинала, который вы выбираете несколько раз, когда используется небольшое изменение состояния. Работает, но ужасно (плюс риск будущих ошибок).
  • Используйте execute immediate, который я действительно ненавижу - PL/SQL отлично подходит для интеграции языка сценариев и SQL (например, подсветка синтаксиса). execute immediate деградирует PL/SQL для вызова SQL по строкам на любом языке (по сравнению с теми, у которых нет многих функций).
  • Используйте временную таблицу, содержимое которой затем будет скопировано в переменную таблицы. Это лишний ненужный код мусора (код должен быть читаемым и иметь смысл).

Есть ли другой способ?

+1

https://docs.oracle.com/database/121/LNPLS/composites.htm#LNPLS00508 –

ответ

1

Правильное решение применить политику VPD для базовых таблиц (бит вы скрыли в (...). Таким образом, коллекция PL/SQL может быть заселен только с данными, которые пользователь сможет увидеть.

мелкозернистый контроль доступа является довольно мощным Кроме того, выпекаются в Oracle, является способ более надежен, чем наши руки прокатке код Find out more

+0

Извините, я, вероятно, использовал другой пример пользователя/ролей. Пользователи определены для приложения вне Oracle и не знают (не должны) даже о Oracle. Роли пользователей не ограничивают доступ к данным в Oracle, а скорее разные блоки и т. Д.Использование системы безопасности Oracle оказалось несовместимым с нашими требованиями (слишком сложным с одной стороны, слишком узким на другом). –

2

Я бы фильтровать запрос на выборку, которая предоставляет данные, что-то вроде:...

select user_role_ty (username, role_nam) 
    bulk collect into p_user_role_list 
from user_role_table 
where case when is_vendor(...) = 'Y' then role_nam 
      when is_admin(...) = 'Y' and role_nam in (<list of roles that the is_admin user is allowed to see>) 
       then role_nam 
     end = role_nam 
or  username = p_username; 
+0

Это самое простое решение. В этом разница между информацией и знаниями. Большое спасибо. –

2

Предыдущие предложения на месте (выполняйте большую часть работы, как вы можете в SQL, или «глубже» и настройте роли виртуальной частной базы данных). Но если вам действительно нужно (или нужно) придерживаться решения, ориентированного на PL/SQL, помните, что после того, как вы собрали массу в эту коллекцию, это переменная PL/SQL.

Так что я бы не думал об использовании EXECUTE IMMEDIATE или временной таблицы, так же, как писать логику PL/SQL для применения любых сложных правил, которые у вас есть.

DECLARE 
    p_user_role_list user_role_ty; 
BEGIN 
    SELECT user_role_ty (username, role_nam) 
    BULK COLLECT INTO p_user_role_list 
    FROM (SELECT 'steven' username, 'admin' role_nam FROM DUAL); 

    FOR indx IN 1 .. p_user_role_list.COUNT 
    LOOP 
     /* Apply changes like .DELETE to remove an element 
     or even copy the elements you want to keep to 
     a new collection */ 
     NULL; 
    END LOOP; 
END; 
/

PS - Я понимаю, ненавидя использовать EXECUTE IMMEDIATE, если вы на самом деле не нужно, но когда вам нужно выполнить динамический SQL, это, безусловно, предлагает хороший, простой, родной способ, чтобы получить работу сделанный!

+1

Стив, если это действительно ты, разве твоя репутация не будет больше похожа на 68к? ;-) Во всяком случае, приятно видеть вас на SO! – tbone

+1

Спасибо, tbone. Да, это я, как в SF, который писал эти книги на PL/SQL. Полагаю, у меня должен быть более высокий балл. Но для этого мне пришлось бы тратить больше времени на SO - и тогда у меня был бы более высокий балл, но у других отлично отличных разработчиков Oracle Database были бы более низкие оценки. И это не кажется правильным. :-) –

+0

Ха-ха! У меня есть ваши книги, отличная работа, они очень помогли мне. – tbone