这是我的代码;-
CREATE OR REPLACE PROCEDURE GetDeails
(c_name VARCHAR2,
calories NUMBER)
DECLARE
CURSOR cur IS SELECT CATEGORY.Name FROM CATEGORY INNER JOIN FILLING ON CATEGORY.CategoryID = FILLING.CategoryID
WHERE c_name=FillING.Name AND calories=GramCalories;
fil cur%ROWTYPE;
BEGIN
OPEN cur;
LOOP
FETCH cur INTO fil;
EXIT WHEN (cur%NOTFOUND);
IF fil%NOTFOUND THEN
DBMS_OUTPUT.PUTLINE('NotFound');
ELSE
DBMS_OUTPUT.PUTLINE(fil.c_name, fil.calories);
END IF;
END LOOP;
CLOSE cur;
END GetDetails;
/
基本上你的PROCEDURE
语句很好,但有一些小问题,例如:
-
将名称
GetDeails
转换为GetDetails
,以便 将名称与最后一个END
后末尾给出的名称匹配 关键词。事实上,两次使用PROCEDURE
的名字是多余的,所以, 不需要。 -
IN参数列表后面应该有
IS
或AS
关键字,并且应该删除关键字DECLARE
。 -
DBMS_OUTPUT.PUTLINE
应转换为DBMS_OUTPUT.PUT_LINE
, 并且应该在CURSOR
的SELECT
列表中提供两个匹配的列(Name
和GramCalories
)。
游标 属性不能应用于非游标
FIL
,而可以应用于CUR
SQL> SET serveroutput ON SQL> CREATE OR REPLACE PROCEDURE GetDetails( c_name VARCHAR2, calories NUMBER ) IS CURSOR cur IS SELECT f.Name, c.GramCalories FROM CATEGORY c JOIN FILLING f ON f.CategoryID = c.CategoryID WHERE c_name=f.Name AND calories=GramCalories; fil cur%ROWTYPE; BEGIN OPEN cur; LOOP FETCH cur INTO fil; EXIT WHEN (cur%NOTFOUND); IF cur%NOTFOUND THEN DBMS_OUTPUT.PUT_LINE('NotFound'); ELSE DBMS_OUTPUT.PUT_LINE(fil.name, fil.calories); END IF; END LOOP; CLOSE cur; END; /
@Barbaros的答案解决了您的大部分问题,但可以进一步完善。
循环中的 IF 语句是完全不必要的,因为它在执行时永远不会返回 True。如果这是真的,退出 它前面的语句将退出循环;因此没有消息。这是多余的;在结果已知的情况下进行测试。 您可以颠倒顺序并将退出放在 IF...如果结束。但是,始终会生成"未找到"消息。您可以在循环后使用 cur%rowcount 来正确生成消息。
dbms_output_put_line(fil.name,fil.calories) 有 2 个错误。
- 变量 fil.calories 不存在。GramCalories 在您的原始版本中没有被选中(如前所述),也没有在修订版中混叠。所以不是游标的一部分,因此不是 游标行类型。
- 它需要一个字符串参数,因为有 2 个参数。
考虑到这些,我们得到:
create or replace procedure getdetails( c_name varchar2, calories number ) is
cursor cur is
select f.name, c.gramcalories
from category c
join filling f
on f.categoryid = c.categoryid
where c_name=f.name
and calories=gramcalories;
fil cur%rowtype;
begin
open cur;
loop
fetch cur into fil;
exit when (cur%notfound);
dbms_output.put_line(fil.name || ' ' || fil..gramcalories);
end loop;
if cur%rowcount = 0 then
dbms_output.put_line('Not Found');
end if;
close cur;
end getdetails;
/
作为风格问题:
- 避免驼峰命名约定。Oracle 始终将对象名称折叠为大写。因此,它只会使 Oracle 生成的引用难以阅读。请改用下划线 (_) 分隔的单词。
- 与巴巴罗斯不同,我不考虑使用该程序(功能, 包装,...终止端的名称是多余的,但更像是一个 关闭和"结束如果"一样多。是的,它在语法上是可选的,但是 可选与冗余不同。我总是行使这个选择。 所以发展了你的风格(取决于机构/客户的要求) 标准),但要与之保持一致。