Oracle,限制每个用户的行数

Oracle, limit the row number per user

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

有人知道这是否可行吗?

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

这个问题的答案真的很复杂。

您可以获取 SQL 并从中创建一个 SQL 计划,并根据估计成本 and/or 估计行的数据限制。

How To Create and Evolve a SQL Plan Baseline

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

示例: 我将创建一个临时 table:

create table tmp_table2 as
   select * from user_objects;

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

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;

结果;

==>
PL/SQL block executed
Too many rows

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

Using the Database Resource Manager

您可以使用游标来实现。参见示例:

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

如果您有企业版,您可以使用 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>