我有卖票的DB。我有这样的程序,我从一些种族中计算所有卖出的钱:
CREATE OR REPLACE PROCEDURE Total_money(depart IN RACE.DEPART_PLACE%TYPE,
dest IN RACE.DESTINATION_PLACE%TYPE, total OUT TICKET.PRICE%TYPE)
IS
CURSOR tickets
IS SELECT t.CLIENT_ID, t.PRICE FROM TICKET t JOIN VAGON v ON t.VAGON_ID = v.VAGON_ID
JOIN RACE r ON v.RACE_ID = r.RACE_ID
WHERE r.DEPART_PLACE = depart AND r.DESTINATION_PLACE = dest;
BEGIN
FOR t IN tickets
LOOP
IF t.CLIENT_ID IS NOT NULL THEN
total := total + t.PRICE;
END IF;
END LOOP;
END;
第一个问题:我可以在CURSOR
声明中添加例外吗?或者当我通过错误的出发名称或火车的目的地名称时,我该怎么办?或者这些名称在DB中不存在。然后它将创建一个空光标。并返还0钱。如何控制?
第二个问题:在程序声明之后,我运行这些命令:
DECLARE t TICKET.PRICE%TYPE;
t:=0;
execute total_money('Kyiv', 'Warsaw', t)
但是有一个错误(PLS-00103遇到符号......) 第一个问题:如何解决?
答案 0 :(得分:1)
一个简单的检查就是测试循环后total
是否为非零:
...
END LOOP;
IF total <= 0 THEN
RAISE_APPLICATION_ERROR(-20001, 'Toal zero, invalid arguments?');
END IF;
END;
如果总数合法地为零(这似乎不太可能,除了客户端ID检查),你可以有一个标志的计数器并检查:
CREATE ... IS
found BOOLEAN := false;
CURSOR ...
BEGIN
total := 0;
FOR t IN tickets
LOOP
found := true;
IF t.CLIENT_ID IS NOT NULL THEN
total := total + t.PRICE;
END IF;
END LOOP;
IF NOT found THEN
RAISE_APPLICATION_ERROR(-20001, 'No records, invalid arguments?');
END IF;
END;
execute
是一个SQL * Plus命令,因此我不确定您希望这种方式工作的方式。你可以使用这样的匿名块:
DECLARE
t TICKET.PRICE%TYPE;
BEGIN
total_money('Kyiv', 'Warsaw', t);
-- do something with t
END;
/
或者使用SQL * Plus(或SQL Developer)变量,您可以这样做:
variable t number;
execute total_money('Kyiv', 'Warsaw', :t);
print t
我将它从程序改为功能;在其中声明一个总数,将其初始化为零,然后返回该参数而不是out
参数。然后,您可以通过简单的选择从PL / SQL或SQL中调用它。
正如ElectricLlama指出的那样,你不需要光标;并且根本不需要在PL / SQL中执行此操作 - 只需使用聚合sum()
。我认为这是一个学习游标的练习吗?