0

我有一个 PL/SQL 过程。它执行一条 SQL 语句并返回一个 json 响应。

我想限制使用 offset 子句返回的行。例如:

select *    
from wherever
where something = parameter
offset 0 rows 
fetch next 25 rows only;

但是,我似乎无法使用变量来替换上面示例中的 0 和 25。

当然,有一些方法可以解决这个问题。我可以像在 11g 中出现偏移子句之前那样编写代码。但它看起来很难看,可能表现不佳....我错过了什么吗?proc或游标中SQL的offset子句中可以使用参数吗?

例如,以下过程确实编译但返回的光标始终为空(当我在值中硬编码时不是):

procedure test (pPageSize in pls_integer:=25, pPageno in pls_integer:=1, RecipeList out sys_refcursor) is
      vNextRows pls_integer;
      vOffset pls_integer; 
    begin
        vOffset:= pPageSize*(pPageno-1);
        vNextRows:= pPageSize;          

        open RecipeList 
            for
            select *      
            from recipes       
            order by recipeno
            offset vOffset rows 
            fetch next vNextRows rows only; 
       
end test;  
4

3 回答 3

2

当您将过程称为

test (null, null, :bind_rc)

您正在覆盖默认值;如果要使用默认值,则不要提供前两个参数:

test (RecipeList => :bind_rc)

或者,如果您不想使用默认值,请提供参数:

test (10, 11, :bind_rc)
test (pPageSize >= 10, pPageno => 2, RecipeList => :bind_rc)

或将大小保留为默认值但获取特定页面:

test (pPageno => 3, RecipeList => :bind_rc)

db<>小提琴


从文档中

您声明的形式参数的默认值。表达式的数据类型必须与数据类型兼容。

如果子程序调用没有为形参指定实参,则该调用计算表达式并将其值分配给形参。

如果子程序调用确实为形参指定了实参,则该调用将实参的值分配给形参并且不对表达式求值。

正在指定实际参数。您传递的是 null,但这意味着您将形式参数指定为 null - 而不是您根本没有指定它们。一个微妙但重要的区别。


我想如果我愿意的话,我可以在 proc 中手动设置默认值。

是的,相当简单:

vOffset:= nvl(pPageSize, 25) * (nvl(pPageno, 1) -1);
vNextRows:= nvl(pPageSize, 25);

db<>小提琴

于 2020-07-15T15:55:59.153 回答
1

我尝试过这个。

如果您将值传递给过程,它工作正常。它不适用于默认值。

-- 创建过程

SQL> CREATE OR replace PROCEDURE TEST1 (
  2  PPAGESIZE    IN    PLS_INTEGER:= 5, -- or default 5
  3  PPAGENO      IN    PLS_INTEGER:= 1, -- or default 1
  4  RECIPELIST   OUT   SYS_REFCURSOR
  5  ) IS
  6  VNEXTROWS   PLS_INTEGER;
  7  VOFFSET     PLS_INTEGER;
  8  BEGIN
  9  VOFFSET     := PPAGESIZE * ( PPAGENO - 1 );
 10  VNEXTROWS   := PPAGESIZE;
 11  OPEN RECIPELIST FOR SELECT *
 12                        FROM T
 13                       ORDER BY A OFFSET VOFFSET ROWS
 14   FETCH NEXT
 15  VNEXTROWS ROWS ONLY;
 16  END TEST1;
 17  /

Procedure created.

-- 不使用默认值

SQL> var res refcursor;
SQL> exec TEST1(null,null,:res);

PL/SQL procedure successfully completed.

SQL> print :res;

no rows selected

-- 使用非默认值

SQL> exec TEST1(5,1,:res);

PL/SQL procedure successfully completed.

SQL> print :res;

         A          B          C
---------- ---------- ----------
         1          1          2
         3                     2
         4          3          4
         8          9          6
        12         12         12

SQL>
于 2020-07-15T15:22:56.893 回答
0

像这样:

declare
  start_row integer := 0;
  fetch_rows integer := 5;
begin
  
  dbms_output.put_line ( 'First ' || fetch_rows );
  for t in ( 
    select * from all_tables 
    offset start_row rows 
    fetch first fetch_rows rows only 
  ) loop
    dbms_output.put_line ( t.table_name );
  end loop;
  
  start_row := 5;
  dbms_output.put_line ( 'Next ' || fetch_rows );
  for t in ( 
    select * from all_tables 
    offset start_row rows 
    fetch first fetch_rows rows only 
  ) loop
    dbms_output.put_line ( t.table_name );
  end loop;
end;
/
于 2020-07-15T14:11:30.230 回答