2016-10-04 9 views
1

私は現在、(パラメータp_Paidに基づいて)支払った金額に等しい金額を支払うことを認識する「Pay」という新しい手続きでPL/SQLを実行しようとしています(パラメータp_Priceに基づいて)必要な値よりも大きいかどうかを判定します。PL/SQL - 必要に応じて正確な変更を行う支払いシステム

p_Pricep_Paidの違いは、可変v_Returnです。

あなたは(p_Paid)以下(p_Price)頼まれたものよりを支払うときp_Paid = p_Price、(例えば、10 = 10)が、それはそれが必要その後、

"No money to return!" 

を言うべき正確な金額を支払いますテキスト

"You're some short!"

を示しそして、あなたは(p_Priceを)頼まれたものよりも(p_Paid)以上を支払うとき、それはあなたが変更与える必要があります20ドル、10ドル、5ドル、1ドル紙幣を使用し、各タイプの請求書の正確な数を示す。

9 $20 bill(s) 
1 $10 bill(s) 
1 $5 bill(s) 
1 $1 bill(s) 

この手順では、すべてが整数(関与なしセント)であることを前提としていますp_Paid場合、それは正確な変化の差を示すべき、206及びp_Priceは10でした。

は、これまでのところ私は、お支払いは価格に等しい、または価格、未満だったときに認識するための手順を取得するために管理しているが、私はお金の戻り部分を取得する方法を把握しようと恐ろしい時間を過ごしています彼らがのために頼まれた以上のものを支払ったときに働くこと。どんな助けでも大いに感謝されるでしょう。これは私がこれまで持っているものである(それが見えるかもしれませんどのように複雑に事前に謝罪、私はちょうどPL/SQLを学び始めた):

CREATE OR REPLACE procedure Pay 
(p_Price IN number, 
p_Paid IN number) 

AS 
v_Return number; 
v_20 number; 
v_10 number; 
v_5 number; 
v_1 number; 

BEGIN 
v_Return := (p_Price - p_Paid); 
v_20 := 0; 
v_10 := 0; 
v_5 := 0; 
v_1 := 0; 

IF v_Return = 0 THEN 
dbms_output.put_line('No money to return!'); 
    ELSE 
    IF p_Price > p_Paid THEN 
    dbms_output.put_line('You're some short!'); 
     ELSE 
     IF p_Price < p_Paid THEN 
     WHILE v_Return > 20 LOOP 
     v_Return := v_Return - 20; 
     v_20 := v_20 + 1; 
     IF v_Return > 10 THEN 
     v_Return := v_Return - 10; 
     v_10 := v_10 + 1; 
     IF v_Return > 5 THEN 
     v_Return := v_Return - 5; 
     v_5 := v_5 + 1; 
     IF v_Return > 1 THEN 
     v_Return := v_Return - 1; 
     v_Return := v_1; 
     dbms_output.put_line(v_20 || '$20 bill(s)'); 
     dbms_output.put_line(v_10 || '$10 bill(s)'); 
     dbms_output.put_line(v_5 || '$5 bill(s)'); 
     dbms_output.put_line(v_1 || '$1 bill(s)'); 
END IF; 
END IF; 
END IF; 
END LOOP; 
END IF; 
END IF; 
END IF; 
END; 
/
+0

「あなたはいくつか短いですよ」で引用符がありません。また、コードをきれいにレイアウトすると、構造に集中するのに役立ちます。 –

答えて

1

を試してみてくださいコード:

  1. あなたはYou're some short!ラインでその単一引用符をエスケープする必要がありますが、私はコピー&ペーストのエラーだと思います。

  2. 逆算すると:v_Returnは負の値になります。 END LOOP;ラインがv_20 := v_20 + 1;行の後でなければなりませんつまり、あなたのEND sが誤って配置されているv_Return := (p_Paid - p_Price);

  3. 半分を、試してみてください。 END IF;の一部にも同じです。

  4. v_Returnがすでに5未満である場合の最後の減算は必要ありません。残りの金額をv_1に割り当ててください。

  5. そして最後には、エラーではなく自体けれども、それはあなたが第二と第三IF s内の最初のIFが、p_Pricep_Paidv_Returnを使用してやっているように、条件をミックスするのは良い考えではありません。 v_Returnを使用していた場合、「あなたはいくつか短いです!」と印刷されていたので、それを逆算していたことに気がつきました。それはしないでください。

EDIT:そして今、あなたはそれを言及することを、それはので、あなたはv_Return > x代わりのv_Return >= xをチェックしていることは事実だが、v_Returnが正確xあるとき、それはそれに気付かないだろうと下位単位(1 $ 5の変更を返します。 1つの$ 10の代わりに10ドルの変更に対して5ドルの1つ)。したがって、>=を使用してください。

だからあなたのコードは、この(私はそれをテストし、それがOKを作品)のようにする必要があります:ちょうど楽しみのために

CREATE OR REPLACE procedure Pay 
(p_Price IN number, 
p_Paid IN number) 

AS 
v_Return number; 
v_20 number; 
v_10 number; 
v_5 number; 
v_1 number; 

BEGIN 
v_Return := (p_Paid - p_Price); 
v_20 := 0; 
v_10 := 0; 
v_5 := 0; 
v_1 := 0; 

IF v_Return = 0 THEN 
dbms_output.put_line('No money to return!'); 
    ELSE 
    IF v_Return < 0 THEN 
    dbms_output.put_line('You''re some short!'); 
     ELSE 
     WHILE v_Return >= 20 LOOP 
     v_Return := v_Return - 20; 
     v_20 := v_20 + 1; 
     END LOOP; 
     IF v_Return >= 10 THEN 
     v_Return := v_Return - 10; 
     v_10 := v_10 + 1; 
     END IF; 
     IF v_Return >= 5 THEN 
     v_Return := v_Return - 5; 
     v_5 := v_5 + 1; 
     END IF; 
     v_1 := v_Return; 
     dbms_output.put_line(v_20 || '$20 bill(s)'); 
     dbms_output.put_line(v_10 || '$10 bill(s)'); 
     dbms_output.put_line(v_5 || '$5 bill(s)'); 
     dbms_output.put_line(v_1 || '$1 bill(s)'); 
END IF; 
END IF; 
END; 
/
+0

ありがとうございます!コードは間違いなく今働いていますが、私はそれが私が望むことをしないことを発見しました。例えば、exec(10,20)のように入力すると、明白な1 $ 10の請求書ではなく、1つの$ 5請求書と5つの$ 1請求書が表示されます。言い換えれば、それは物事を過度に複雑にする。より大きな請求書を最初に提出することを「賢く」認識させる方法はありますか?ありがとうございました! – Art

+0

確かに、あなたはそれを受け入れることができるように私の答えを編集します:)編集:そこに行く! – walen

+0

あなたは素晴らしいです!ありがとうございました!私はそれがメモ帳ファイルにすべてのコードを入力するのに役立たないと思います。間違いなく「You''reに起こったようなエラーをキャッチするためにすべてを色分けする構文エディタを見なければなりません。編集:魅力のように動作し、再度あなたに感謝walen!このコードを勉強して、次の手順をどのように改善できるかについて学びます。 – Art

0

あなたにはエラーがあります

v_20 := floor(v_return/20); 
tmp:= v_return - v_20*20; 
v_10 := floor(tmp/10); 
tmp:= v_return - v_20*20 - v_10 * 10; 
v_5 := floor(tmp/5); 
v_1 := tmp - v_5*5; 
+0

残念ながら、それは私が作ろうとしている手順ではうまくいかないが、試してくれてありがとう。他の誰かが解決策を持っていますか? – Art

+0

なぜプロシージャで動作しないのですか?手続き中のローカル変数にtmpを追加するだけで、p_paid> p_priceのときには動作します – Kacper

1

、ここではより構造化されたバージョンです。 (通貨額をフォーマットしchange()手順は、パッケージの一部として良いだろうが、私はデモ便宜上pay()プロシージャ内でそれらを入れ子になってきましたmoney()機能。)

create or replace procedure pay 
    (p_price pls_integer 
    , p_paid pls_integer) 
as 
    v_remainder pls_integer := p_paid - p_price; 

    type change_list is table of pls_integer index by pls_integer; 
    v_change change_list; 

    function money 
     (p_amount pls_integer) 
     return varchar2 
    is 
    begin 
     return to_char(p_amount,'fmL99999'); 
    end money; 

    procedure change 
     (p_amount in out nocopy pls_integer 
     , p_denomination in pls_integer 
     , p_change in out nocopy change_list) 
    is 
    begin 
     if p_amount >= p_denomination then 
      p_change(p_denomination) := trunc(p_amount/p_denomination); 
      p_amount := mod(p_amount,p_denomination); 
     else 
      p_change(p_denomination) := 0; 
     end if; 

     dbms_output.put_line 
     (p_change(p_denomination) || ' ' || money(p_denomination) || ' bill' || 
      case when p_change(p_denomination) <> 1 then 's' end); 
    end change; 

begin 
    if p_paid > p_price then 
     dbms_output.put_line 
     ('Price ' || money(p_price) || 
      ', Paid ' || money(p_paid) || ': Change due ' || money(v_remainder) || ', as:'); 

     change(v_remainder, 20, v_change); 
     change(v_remainder, 10, v_change); 
     change(v_remainder, 5, v_change); 
     change(v_remainder, 1, v_change); 
    else 
     dbms_output.put_line 
     (case 
       when p_paid = p_price then 'No change due.' 
       else 'Please enter an additional ' || money(p_price - p_paid) 
      end); 
    end if; 
end; 

例:

SQL> exec pay(73, 100) 
Price $73, Paid $100: Change due $27, as: 
1 $20 bill 
0 $10 bills 
1 $5 bill 
2 $1 bills 

SQL> exec pay(73, 50) 
Please enter an additional $23 

$ 50の請求書を追加する方がはるかに簡単になることに注意してください。

change()への4回の呼び出しは、ループとして再構成できますが、ループを構築する必要があり、実際にはあまり効果がありません。

関連する問題