CREATE OR REPLACE PROCEDURE test_max_rows (
max_rows IN NUMBER DEFAULT 1000
)
IS
CURSOR cur_test ( max_rows IN number ) IS
SELECT id FROM test_table
WHERE user_id = 'ABC'
AND ROWNUM <= max_rows;
id test_table.id%TYPE;
BEGIN
OPEN cur_test(max_rows) ;
LOOP
FETCH cur_test INTO id;
EXIT WHEN cur_test%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('ID:' || id);
END LOOP;
END;
我的要求是修改上面的代码,这样当我为max_rows传递-1时,proc应该返回查询返回的所有行。否则,它应该按照max_rows限制行。
例如:
EXECUTE test_max_rows(-1);
此命令应返回上述SELECT语句返回的所有行。
EXECUTE test_max_rows(10);
此命令应仅返回10行。
答案 0 :(得分:2)
您可以使用OR
子句执行此操作;改变:
AND ROWNUM <= max_rows;
为:
AND (max_rows < 1 OR ROWNUM <= max_rows);
然后传递零,-1或任何负数将获取所有行,任何正数将返回受限列表。您也可以用default 1000
替换default null
子句,然后测试null,这可能会更明显一些:
AND (max_rows is null OR ROWNUM <= max_rows);
请注意,使用传递值获得的行将是不确定的,因为您目前没有order by
子句。
在程序中执行此操作似乎有点奇怪,并且您假设无论谁调用它都能够看到输出 - 即将完成set serveroutput on
或等效的客户端 - 这是不是一个非常安全的假设。另一种方法是,如果你不能在一个简单的查询中指定行限制,可能是使用流水线函数 - 你至少可以从普通的SQL中调用它。
CREATE OR REPLACE FUNCTION test_max_rows (max_rows IN NUMBER DEFAULT NULL)
RETURN sys.odcinumberlist PIPELINED
AS
BEGIN
FOR r IN (
SELECT id FROM test_table
WHERE user_id = 'ABC'
AND (max_rows IS NULL OR ROWNUM <= max_rows)
) LOOP
PIPE ROW (r.id);
END LOOP;
END;
/
然后将其称为:
SELECT * FROM TABLE(test_max_rows);
或
SELECT * FROM TABLE(test_max_rows(10));
Here's a quick SQL Fiddle demo。但是你仍然应该考虑是否可以在纯SQL和PL / SQL中完成整个过程。