Использование курсора для определения курсора - PullRequest
0 голосов
/ 03 мая 2018

В настоящее время я пытаюсь получить доступ к общей сумме задолженности и общей суммы, уплаченной за каждый расход, из финансовой базы данных. Чтобы уточнить, скажем, у меня есть 5 расходов. В каждом расходе есть много предметов, итоги которых можно сложить, чтобы получить общую сумму своих расходов. Расходы также имеют сумму, которая уже была оплачена. Мне нужно отобразить, равны ли эти числа (причитающиеся и оплаченные) для каждого расхода в таблице. У меня есть следующее:

SET ECHO OFF
SET VERIFY OFF
SET SERVEROUTPUT ON

DECLARE
    paid NUMBER;
    owed NUMBER;
    ExpNumber NUMBER;

    CURSOR CurrentNum IS
    SELECT ExpNum FROM ExpMast;
    CURSOR walkthrough IS

        SELECT SUM(Amt)
        FROM ExpDet WHERE ExpNum = ExpNumber;

    CURSOR wlkthr IS 
        SELECT SUM(CashAmt+Amt) FROM
        ExpMast NATURAL JOIN ExpByCC WHERE ExpNum = ExpNumber;

BEGIN
    OPEN walkthrough;
    OPEN wlkthr;
    OPEN CurrentNum;
    LOOP
        FETCH walkthrough INTO owed;
        FETCH wlkthr INTO paid;
        FETCH CurrentNum INTO ExpNumber;
        EXIT WHEN CurrentNum%NOTFOUND;  
        DBMS_OUTPUT.PUT_LINE('Calculating expenses for Exp: ' || ExpNumber);
            IF paid = owed THEN
                DBMS_OUTPUT.PUT_LINE('All Expenses paid. Total: ' || owed);

            ELSE
                DBMS_OUTPUT.PUT_LINE('Amount Paid: ' || paid);
                DBMS_OUTPUT.PUT_LINE('Total Owed: ' || owed);
                DBMS_OUTPUT.PUT_LINE('Difference: ' || (owed-paid));
            END IF;              
    END LOOP;
    CLOSE walkthrough;
    CLOSE wlkthr;
    CLOSE CurrentNum;
END;
/
SET VERIFY ON
SET ECHO ON 

Однако, когда я запускаю это, он показывает задолженность и оплату за каждый счет как ноль. Любые идеи относительно того, где я ошибаюсь с моим кодом?

Ответы [ 2 ]

0 голосов
/ 03 мая 2018

Вы можете реализовать это в одном запросе SQL

select em.ExpNum 
          , nvl(ed.owed, 0) as owed
          , nvl(ecc.cc_paid, 0) + em.CashAmt as paid
          , nvl(ed.owed, 0) - (nvl(ecc.cc_paid, 0) + em.CashAmt) as diff
from ExpMast em
        left join ( select ExpNum, sum(Amt) as owed 
                    from ExpDet 
                    group by ExpNum ) ed
            on ed.ExpNum  = em.ExpNum  
        left join  ( select ExpNum, sum(Amt) as cc_paid 
                    from ExpByCC 
                    group by ExpNum ) ecc
            on ecc.ExpNum  = em.ExpNum    
order by em.ExpNum

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

Вот скрипта SQL .


Кроме того, вам следует избегать использования естественных объединений. Да, стандарт ANSI SQL поддерживает их, и да, полезно знать, что они существуют. Но в реальной жизни это просто ошибка, ожидающая своего появления.

0 голосов
/ 03 мая 2018

В вашем коде есть небольшая ошибка последовательностей открытия курсора, я все их исправил. Курсор "CurrentNum" является курсором драйвера для других курсоров, поэтому вам нужно открыть два других курсора внутри цикла курсора драйвера. Ниже приведен правильный вариант, проверьте, надеюсь, он решит вашу задачу.

DECLARE
    paid NUMBER;
    owed NUMBER;
    ExpNumber NUMBER;

CURSOR CurrentNum IS
    SELECT ExpNum FROM ExpMast;

    CURSOR walkthrough IS
        SELECT SUM(Amt)
        FROM ExpDet WHERE ExpNum = ExpNumber;

    CURSOR wlkthr IS
        SELECT SUM(CashAmt+Amt) FROM
        ExpMast NATURAL JOIN ExpByCC WHERE ExpNum = ExpNumber;
BEGIN
    OPEN CurrentNum;
    LOOP
        FETCH CurrentNum INTO ExpNumber;
        EXIT WHEN CurrentNum%NOTFOUND;
        DBMS_OUTPUT.PUT_LINE('Calculating expenses for Exp: ' || ExpNumber);

        OPEN walkthrough;
        FETCH walkthrough INTO owed;

        OPEN wlkthr;
        FETCH wlkthr INTO paid;

        IF paid = owed THEN
                DBMS_OUTPUT.PUT_LINE('All Expenses paid. Total: ' || owed);

            ELSE
                DBMS_OUTPUT.PUT_LINE('Amount Paid: ' || paid);
                DBMS_OUTPUT.PUT_LINE('Total Owed: ' || owed);
                DBMS_OUTPUT.PUT_LINE('Difference: ' || (owed-paid));
            END IF;
        CLOSE walkthrough;
        CLOSE wlkthr;
    END LOOP;
    CLOSE CurrentNum;
END;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...