【问题标题】:How to return rows based on the database user and the table's contents?如何根据数据库用户和表的内容返回行?
【发布时间】:2019-11-30 19:38:49
【问题描述】:

我有一张下表:

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

我想在 Oracle SQL 中创建一个策略函数来确保以下几点:

  1. 如果用户(Leo)在该表上执行选择语句,它只会得到3 LEO 4
  2. sys_dba 无论如何都会得到所有结果。

我已授予 Leo 在 Scott 创建的这张桌子上的选择权限。

我在编写这个复杂的 PL/SQL 函数时遇到了困难。我尝试了以下方法,它指出了编译错误。另外,我认为它没有做我打算做的事情:

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;
/

【问题讨论】:

  • 嗯?对不起,但你的功能没有任何意义。所以你想限制根据 oracle 用户名选择哪些记录?
  • 是的,完全正确。 sys_dba 获取所有记录。
  • 如果您至少有版本 11(¿release 2?},您可能需要查看“标签安全性”。
  • @Abecee - 我想你的意思是Virtual Private Database(因为标签安全是企业版的额外收费)。但即使是 VPD 也需要 EE,并且在标准版中不可用,尽管有趣的是它在 Oracle 18c XE 中得到支持。
  • @APC:实际上,我确实考虑过标签安全性。似乎确实解决了这种情况。但这只是与技术相关的评论 - 忽略了任何许可问题。

标签: oracle stored-functions


【解决方案1】:

根据您之前发布的问题和信息,我是这样理解这个问题的:如果您将整个表上的select 授予任何用户,那么它就能够从中获取 all 行它。您必须进一步限制值。

一种选择——正如我们所说的函数——是在where 子句中使用case

这是一个例子。

样本数据:

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.

功能:

  • 它接受用户名作为参数(注意字母大小写!在我的示例中,所有内容都是小写的。在您的情况下,也许您必须使用upper 函数或类似的东西)
  • case 说:如果 par_user 等于 sys,让它获取所有行。否则,仅获取 name 列的值等于 par_user 的行
  • 返回结果

所以:

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.

让我们试试吧:

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

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

SQL>

【讨论】:

  • 对我来说,这似乎限制了基于函数参数而不是用户执行它的结果。除此之外,OP 似乎(至少对我而言)要求对普通ˋSELECTˋ 有效的解决方案。请问我错过了什么?
  • 你错过了我写的第一句话,@Abecee。此问题与同一人之前发布的问题有关。
  • 之前的问题似乎是stackoverflow.com/questions/59118281/… - 这是关于实施安全策略的问题……没关系。
【解决方案2】:

我建议为每个用户创建一个视图,像这样

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

然后仅授予对视图的访问权限。
现在,用户尝试在您的表上执行什么样的查询并不重要,她只会得到一行。
当然 DBA 用户可以访问所有的表数据。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-05
    • 1970-01-01
    • 1970-01-01
    • 2016-04-25
    • 2021-06-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多