Oracle,限制每个用户的行号

时间:2016-01-25 12:35:04

标签: oracle configuration

我需要限制查询可以为特定用户返回的行数。我知道我可以限制SQL查询,但我需要避免特定用户可以构建返回大量行的查询。因此我需要限制配置。

有人知道是否有可能吗?

3 个答案:

答案 0 :(得分:1)

如果您有Enterprise Edition,则可以使用DBMS_RLS包实现VPD规则:

SQL> create or replace package pac1
  2  is
  3    function limit_rows(owner varchar2, tab varchar2) return varchar2;
  4    end;
  5  /

Package created.

SQL> create or replace package body pac1
  2  is
  3    function limit_rows(owner varchar2, tab varchar2) return varchar2
  4    is
  5    begin
  6      return ' rownum <= 3';
  7    end;
  8  end pac1;
  9  /

Package body created.

SQL> begin
  2    dbms_rls.add_policy('HR','EMPLOYEES','RULE1','HR','PAC1.LIMIT_ROWS','SELECT');
  3  end;
  4  /

PL/SQL procedure successfully completed.


SQL> select first_name, last_name from hr.employees;

FIRST_NAME           LAST_NAME
-------------------- -------------------------
Ellen                Abel
Sundar               Ande
Mozhe                Atkinson

SQL>

答案 1 :(得分:0)

数据量不一定等于负载量。单行查询可以杀死数据库,如果它足够复杂的话。

对此的回答非常复杂。

您可以从中获取SQL并从中创建SQL PLAN,并从估计的成本和/或估计的行中获取该数据限制。

How To Create and Evolve a SQL Plan Baseline

How do I display and read the execution plans for a SQL statement

实施例: 我将创建一个临时表:

for header, values := range resp.Header {
    for _, value := range values {
        log.Printf("\t\t %s %s", header, value)
    }
}

然后我使用Oracle的计划估算而没有实际运行查询

create table tmp_table2 as
   select * from user_objects;

结果;

declare
   l_sql   varchar2 (32767);
begin
   delete from plan_table;
   l_sql := 'select * from tmp_table2';
   execute immediate 'explain plan for ' || l_sql;
   for i in (select cardinality,
                    cost,
                    bytes,
                    cpu_cost
               from PLAN_TABLE
              where operation = 'SELECT STATEMENT') loop
      if i.cardinality /* rows */
                      > 500 then
         dbms_output.put_line ('Too many rows');
      elsif i.cpu_cost > 500000 then
         dbms_output.put_line ('Too much CPU');
      else
         dbms_output.put_line ('About right');
      end if;
   end loop;
end;

或者您可以使用资源管理器限制每个会话:

Using the Database Resource Manager

答案 2 :(得分:0)

您可以使用游标实现此目的。见例:

SQL> create or replace function exec_query(sql_text varchar2) return sys_refcursor
  2  is
  3    num_rows number := 3;
  4    c1 sys_refcursor;
  5  begin
  6    open c1 for 'with test as (' || sql_text || ') select * from test where rownum <=' || num_rows ;
  7    return c1;
  8  end;
  9  /

Function created.

SQL> variable c1 refcursor;

SQL> exec :c1 := exec_query('select last_name, salary from hr.employees');

PL/SQL procedure successfully completed.


SQL> print :c1;

LAST_NAME                     SALARY
------------------------- ----------
King                           24000
Kochhar                        17000
De Haan                        17000