How to return rows based on the database user and the table's contents?

℡╲_俬逩灬. 提交于 2020-01-06 05:26:52

问题


I have a following table:

id name       score
 1 SYS        4
 2 RHWTT      5
 3 LEO        4
 4 MOD3_ADMIN 5
 5 VPD674     4
 6 SCOTT      5
 7 HR         4
 8 OE         5
 9 PM         4
10 IX         5
11 SH         4
12 BI         5
13 IXSNEAKY   4
14 DVF        5

I want to create a policy function in Oracle SQL that makes sure of the following things:

  1. If a user(Leo) is executing a select statement on this table, it only gets 3 LEO 4.
  2. sys_dba gets all the results no matter what.

I have given select permissions to Leo on this table created by Scott.

I am getting stuck at writing this complex PL/SQL function. I tried the following and it states compilation errors. Also, I think it does not do what I intend to do:

CREATE FUNCTION no_show_all (
    p_schema    IN NUMBER(5),
    p_object    IN VARCHAR2
)
    RETURN 
AS
BEGIN
    RETURN 'select avg(score) from scott.rating';
END;
/

回答1:


Based on your previous question and info you posted, here's how I understood the question: if you granted select on the whole table to any user, then it is able to fetch all rows from it. You have to further restrict values.

One option - as we're talking about the function - is to use case in where clause.

Here's an example.

Sample data:

SQL> create table rating as
  2    select 1 id, 'sys' name, 4 score from dual union all
  3    select 3,    'leo'     , 3 from dual union all
  4    select 6,    'scott'   , 5 from dual union all
  5    select 7,    'hr'      , 2 from dual;

Table created.

Function:

  • it accepts username as a parameter (mind letter case! In my example, everything is lowercase. In your, perhaps you'll have to use upper function or something like that)
  • case says: if par_user is equal to sys, let it fetch all rows. Otherwise, fetch only rows whose name column's value is equal to par_user
  • return the result

So:

SQL> create or replace function f_rating (par_user in varchar2)
  2    return number
  3  is
  4    retval number;
  5  begin
  6    select avg(score)
  7      into retval
  8      from rating
  9      where name = case when par_user = 'sys' then name
 10                        else par_user
 11                   end;
 12    return retval;
 13  end;
 14  /

Function created.

Let's try it:

SQL> select f_rating('sys') rating_sys,
  2         f_rating('hr')  rating_hr
  3  from dual;

RATING_SYS  RATING_HR
---------- ----------
       3,5          2

SQL>



回答2:


I suggest creating a view for each user, like so

create view THE_VIEW as select * from TABLE where NAME = user

Then grant access to the view only.
Now it doesn't matter what kind of query a user tries to perform on your table, she will only get one row back.
Of-course the DBA user can access all the table data.



来源:https://stackoverflow.com/questions/59119590/how-to-return-rows-based-on-the-database-user-and-the-tables-contents

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!