Я понятия не имею, правильны ли ваши запросы VALID_USER и INVALID_USER, так как вы не предоставили нам свои требования по ним.Но я думаю, что это проблема вашего основного запроса:
with
INVALID_USERS as
(
select
USERNAME
from
DBA_USERS
where
USERNAME like 'SRV_%'
and ACCOUNT_STATUS != 'OPEN'
),
VALID_USERS as (
select
USERNAME
from
DBA_USERS
where
USERNAME not like 'SRV_%'
and (not ACCOUNT_STATUS = 'LOCKED')
)
select *
from
DBA_ROLES drol
where
-- role is assigned to AT LEAST ONE "invalid user"
EXISTS (select 1 from DBA_ROLE_PRIVS drolp where drol.ROLE = drolp.GRANTED_ROLE and GRANTEE in (select USERNAME from INVALID_USERS))
-- and role is not assigned to ANY "valid users"
and NOT EXISTS (select 1 from DBA_ROLE_PRIVS drolp where drol.ROLE = drolp.GRANTED_ROLE and GRANTEE in (select USERNAME from VALID_USERS));
Логика WHERE вашего запроса проверяется один раз для каждой строки в DBA_ROLE_PRIVS, и поэтому GRANTEE всегда будет иметь одно значение - один пользователь.Так что он вернет true только для любого GRANTEE, который входит в ваши VALID_USERS и INVALID_USERS - вероятно, не то, что вы хотите.
Вам необходимо дважды запросить таблицу DBA_ROLE_PRIVS - один раз, чтобы проверить допустимых пользователей, и один раз, чтобы проверить недействительных пользователей.Вы можете обойти это с помощью агрегатных функций, хотя вам придется поместить ваши условия вне GROUP BY - сделать это подзапросом или переместить их в предложение HAVING, например:
with
INVALID_USERS as
(
select
USERNAME
from
DBA_USERS
where
USERNAME like 'SRV_%'
and ACCOUNT_STATUS != 'OPEN'
),
VALID_USERS as (
select
USERNAME
from
DBA_USERS
where
USERNAME not like 'SRV_%'
and (not ACCOUNT_STATUS = 'LOCKED')
)
select GRANTED_ROLE
from
DBA_ROLE_PRIVS drolp
join DBA_ROLES drol on drol.ROLE = drolp.GRANTED_ROLE
group by GRANTED_ROLE
having
-- role is assigned to AT LEAST ONE "invalid user"
sum(CASE when GRANTEE in (select USERNAME from INVALID_USERS) THEN 1 else 0 end) > 0
-- and role is not assigned to ANY "valid users"
and sum(CASE when GRANTEE in (select USERNAME from VALID_USERS) THEN 1 else 0 end) = 0;