根据输入参数显示行数

时间:2014-09-23 09:24:27

标签: sql oracle11g toad

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行。

1 个答案:

答案 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中完成整个过程。