【问题标题】:How do I define another temporary variable and fetch into it?如何定义另一个临时变量并获取它?
【发布时间】:2020-08-05 13:09:11
【问题描述】:
这是我的代码;-
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;
/
【问题讨论】:
标签:
oracle
stored-procedures
plsql
oracle11g
【解决方案1】:
基本上你的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;
/
【解决方案2】:
@Barbaros 的答案解决了您的大部分问题,但可以进一步完善。
循环中的 IF 语句是完全没有必要的,因为它在执行时永远不会返回 True。如果是真的退出
它前面的语句将退出循环;因此没有消息。这是多余的;在已知结果的情况下进行测试。您可以颠倒顺序并将退出放在 IF...END 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;
/
作为风格问题:
- 避免使用 CamelCase 命名约定。 Oracle 总是将对象名称折叠为大写。因此,它只会使 Oracle 生成的引用难以阅读。请改用下划线 (_) 分隔的单词。
- 与巴巴罗斯不同,我不考虑使用过程(函数,
package, ...) 终止端的名称是多余的,但更多的是
关闭与“结束如果”一样多。是的,它在语法上是可选的,但是
optional 不一样是多余的。我总是行使这个选项。
所以发展了你的风格(受制于机构/客户要求
标准),但要与之保持一致。