offset

41ik7eoe  于 2021-07-26  发布在  Java
关注(0)|答案(3)|浏览(437)

我有一个pl/sql过程。它执行一个sql语句并返回一个json响应。
我想限制使用offset子句返回的行。如:

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

然而,在上面的例子中,我似乎无法使用变量来替换0和25。
当然有办法解决这个问题。我可以像11g中出现offset子句之前那样编写代码。但它看起来很难看,可能不会表现得很好…我错过了什么。在过程或游标的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;
ar5n3qh5

ar5n3qh51#

这样地:

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

zfciruhq2#

当你把这个过程称为

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<>小提琴

14ifxucb

14ifxucb3#

我试过了。
如果您将值传递给过程,则工作正常。它不使用默认值。
--创建过程

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>

相关问题