Я пытаюсь просмотреть таблицу в цикле и увеличить количество переменных, если выполняется определенный случай. Он не выдает ошибок, но и не отображает числа для счетчиков дешевых, справедливых и опытных.

CREATE OR REPLACE PROCEDURE product_price_report AS
C_LIST_PRICE PRODUCTS.LIST_PRICE%TYPE;
LIST_PRICE PRODUCTS.LIST_PRICE%TYPE;
avg_price products.list_price%TYPE;
max_price products.list_price%TYPE;
min_price products.list_price%TYPE;
CURSOR PROD_CURSOR IS
    SELECT LIST_PRICE
    FROM PRODUCTS;
cheap_count NUMBER;
fair_count NUMBER;
exp_count NUMBER;
BEGIN

SELECT AVG(LIST_PRICE) INTO avg_price FROM PRODUCTS;
SELECT MAX(LIST_PRICE) INTO max_price FROM PRODUCTS;
SELECT MIN(LIST_PRICE) INTO min_price FROM PRODUCTS;

BEGIN
    OPEN PROD_CURSOR;
    LOOP
        FETCH PROD_CURSOR INTO C_LIST_PRICE;
        EXIT WHEN PROD_CURSOR%NOTFOUND;
        CASE 
            WHEN LIST_PRICE < (AVG_PRICE - MIN_PRICE) / 2 THEN CHEAP_COUNT := CHEAP_COUNT + 1;
            WHEN LIST_PRICE > (MAX_PRICE - AVG_PRICE) / 2 THEN FAIR_COUNT := FAIR_COUNT + 1;
            ELSE EXP_COUNT := EXP_COUNT + 1;
        END CASE;
    END LOOP;
    CLOSE PROD_CURSOR;
    
    DBMS_OUTPUT.PUT_LINE('Cheap: ' || CHEAP_COUNT);
    DBMS_OUTPUT.PUT_LINE('Fair: ' || FAIR_COUNT);
    DBMS_OUTPUT.PUT_LINE('Expensive: ' || EXP_COUNT);
END;

EXCEPTION
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('Too many rows');  
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('No data found');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Undefined error');     
END;
/

BEGIN
product_price_report;
END;
/

Почему это? Благодарность

0
Zelkop 9 Ноя 2020 в 01:18

2 ответа

Лучший ответ

Помимо того, что вы не настроили вывод сервера, ваша процедура имеет другие ошибки, которые не позволят вам получить значимый вывод. Во-первых, вы не инициализировали свои счетчики ни в объявлении, ни в разделе выполнения. В результате они содержат NULL (значение по умолчанию plsql для всех неинициализированных переменных), поэтому результат каждого приращения счетчика сам по себе равен NULL (cheap_count + 1 совпадает с NULL + 1, который равен NULL). Во-вторых, вы вставляете курсор в переменную c_price_list, но затем ваш случай, когда условия относятся к переменной list_price, которая также имеет значение NULL, поэтому каждая строка попадает в условие else этого случая. Одного из них достаточно, чтобы гарантировать неверные результаты.
Хотя это не приводит к неправильным результатам, нет причин для использования отдельных выборок для получения минимальных, средних и максимальных значений - один выбор может получить все 3. Кроме того, нет причин перебирать курсор даже целиком. процесс может быть решен с помощью одного запроса:

with base_line( min_price, avg_price, max_price) as 
    (select min(list_price), avg(list_price), max(list_price)
       from products
    )  
select sum(cheap) chaep, sum(fair) fair, sum(expensive) expensive
  from (select case when list_price < (avg_price - min_price) / 2 then 1 else 0 end as cheap   
             , case when list_price > (max_price - avg_price) / 2 then 1 else 0 end as fair  
             , case when not list_price < (avg_price - min_price) / 2 
                     and not list_price > (max_price - avg_price) / 2 then 1 else 0 end as expensive 
         from products
         cross join base_line 
      ) w;

См. скрипку. В дополнение к вышеуказанному запросу скрипка также содержит исправленную версию вашего исходного сообщения и для сравнения процедуру с использованием вышеуказанного запроса в курсоре (для генерации dbms_output).

Наконец, вы можете просмотреть свои формулы. Использование тестовых строк с list_price 25, 50 и 75 (легко определить min, avg, max). Необходимое значение для классификации дешевой намного меньше минимума. Но это всего лишь один тестовый пример, и, возможно, особенный. Но вы не сообщили дату тестирования и ожидаемые результаты.

1
Belayer 10 Ноя 2020 в 00:03

Добро пожаловать,

  1. вы должны включить / выключить сервер; при использовании sqlplus
  2. dbms_out должен использоваться внутри цикла для этого контекста

Попробуйте и дайте нам знать.

2
nizam 9 Ноя 2020 в 03:57