2014-09-23 3 views
0
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; 

Мое требование состоит в том, чтобы изменить приведенный выше код, чтобы при передаче -1 для max_rows proc должен возвращать все строки, возвращаемые запросом. В противном случае он должен ограничивать строки в соответствии с max_rows.Отображение Количество строк на основе входного параметра

Например:

EXECUTE test_max_rows(-1); 

Эта команда должна вернуть все строки, возвращаемые ЗЕЬЕСТОМ выше.

EXECUTE test_max_rows(10); 

Эта команда должна возвращать только 10 строк.

+0

Затем я предлагаю удалить DEFAULT 1000. После этого вам не понадобится этот 1 взлом. Сообщите вашему приложению, которое использует эту процедуру, чтобы сказать, что ей нужно 1000. Поскольку любое другое решение с текущим выбором побудило бы оператор IF и другой подзапрос определить количество строк в таблице, например. IF max_rows == -1 THEN max_rows = SELECT count (1) FROM table .. – tvm

ответ

2

Вы можете сделать это с помощью статьи OR; изменить:

AND ROWNUM <= max_rows; 

к:

AND (max_rows < 1 OR ROWNUM <= max_rows); 

Затем проходит ноль, -1, или любое отрицательное число будет получать все строки, и любое положительное число, будет возвращать ограниченный список. Можно также заменить пункт default 1000 с default 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 вообще.

+0

Большое спасибо. Хотя я не понял то, что предложил @TVM. Простите мое невежество. Новое для SQL. –

+0

@WamglindCarmasaic - я думаю, что tvm должен был удалить предложение по умолчанию и сделать клиент * всегда * указать количество строк; то есть он должен передавать действительно высокое значение, чтобы убедиться, что все строки включены. Это означает, что ваш клиент достаточно хорошо знает данные, чтобы сделать это безопасно, или сначала запускает запрос, чтобы определить, какой номер использовать. –