在预期以下情况之一时遇到符号“INTO”

Posted

技术标签:

【中文标题】在预期以下情况之一时遇到符号“INTO”【英文标题】:Encountered the symbol "INTO" when expecting one of the following 【发布时间】:2019-01-03 17:53:07 【问题描述】:

我在定义函数时遇到以下错误。 “:...” 我正在从一个网站尝试这个例子。我也想了解这里使用的游标逻辑。

    我们可以从定义部分获取值并关闭游标吗? c1%notfound 块和分配高值 9999 给 p_cid 有什么意义?
create or replace function get_cust_id(p_cname IN varchar2)
RETURN number
IS
p_cid number;

cursor c1 is
select p_cid from customers where c_name = p_cname;

BEGIN

OPEN c1;
FETCH c1 INTO into p_cid;

if c1%notfound
then
p_cid:=9999;
end if;

close c1;

RETURN p_cid;

EXCEPTION
WHEN OTHERS THEN
raise_application_error(-20001,'An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM);
END;

=============================================

上面的“INTO”问题由于拼写错误已得到纠正。

我现在正在尝试调用该函数,但输出与预期不符:

select c_name,get_cust_id(c_name) as cust_id
from customers
where city='London';

输出:

C_NAME  CUST_ID
Alice    - 
Patrick  - 

【问题讨论】:

FETCH c1 INTO into p_cid; 2x INTO 删除其中一个 感谢您的观察。成功了! 顺便说一下,sqlcode 只是已经包含在 sqlerrm 中的错误编号,例如,如果 sqlerrm'ORA-01234: Bananas are not available on a周二' 然后sqlcode 是-1234 和SQLCODE||' -ERROR- '||SQLERRM 给出-1234 -ERROR- ORA-01234:周二不提供香蕉。那有什么意义呢? (编辑:刚刚注意到您的评论我正在从一个网站尝试这个示例。我认为这不是一个很棒的网站。) 好的,我现在了解sqlcodesqlerrm 之间的区别。非常感谢您的意见!如果您能向我推荐一些可以帮助我在 plsql 中构建强大逻辑的网站,那将是非常有帮助的。 【参考方案1】:

除了@Lukasz 在 cmets 中指出的双 into 之外,您的游标查询正在执行此操作:

select p_cid from customers where c_name = p_cname;

这里的p_cid 是你刚刚声明的数字,它还没有被赋值。所以你实际上是在做:

select null from customers where c_name = p_cname;

这就是为什么您的测试查询从函数调用中返回空值的原因。您需要将该查询中的p_cid 更改为表中的列名,我猜这只是idc_id

create or replace function get_cust_id(p_cname IN varchar2)
RETURN number
IS
p_cid number;

cursor c1 is
select c_id from customers where c_name = p_cname;

BEGIN

OPEN c1;
FETCH c1 INTO p_cid;
...

我们可以在定义部分取值并关闭游标吗?

没有。

c1%notfound block 并为 p_cid 分配高值 9999 有什么意义?

如果您传入一个不存在的名称(这不会发生在您调用它的方式上,但无论如何它是非常人为的),那么游标查询将找不到该名称的数据。 fetch 不会抛出错误,但实际上不会检索任何内容。 The %notfound` cursor attribute 为真,因为没有提取任何行。

在这种情况下,if c1%notfound 为真,因此会执行 p_cid:=9999; 语句,然后将该值返回给调用者。

实际上它返回 9999 作为“幻数”,表示没有找到实际的 ID。 (如果发生这种情况,返回 null 或抛出异常可能会更安全 - 幻数可能会在以后引起问题,例如 - 很明显 - 如果您还有一个 ID 为 9999 的真实客户......)

有更简单的方法可以实现此功能的功能,但大概它试图以人为的方式教您特定的东西。

【讨论】:

感谢您的意见!我理解了使用 9999 的概念。我将在接下来的代码中尝试返回 null 并抛出异常。我还想知道应该将什么值传递给函数,以便执行 WHEN OTHERS THEN 块? 好吧,when others then 模式通常不是一个好主意,排除它并让原始异常冒泡到调用者会更简单。我不确定您是否可以制造一种获得异常的方法-由于游标逻辑,您不会得到 no-data-found 或 too-many-rows (如果 c_id 不是唯一的)。如果c_id 是字符串列,那么您可以从非数字字符串值中获取 ORA-01722;但这会更加做作。 感谢您的意见! 块不适用于此代码。【参考方案2】:

当我更改以下行时,输出与预期一致:

select c_id into p_cid from customers where c_name = p_cname;

输出:

C_NAME  CUST_ID
Alice   3
Patrick 6

【讨论】:

以上是关于在预期以下情况之一时遇到符号“INTO”的主要内容,如果未能解决你的问题,请参考以下文章

PLS-00103:在预期以下情况之一时遇到符号“TEST_PKG”:;

错误:PLS-00103:在预期以下情况之一时遇到符号“)”

为啥我会收到此错误? PLS-00103:在预期以下情况之一时遇到符号“CREATE”:

PLS-00103:在预期以下情况之一时遇到符号“END”

PLS00103:在预期以下情况之一时遇到符号“I”

错误:PLS-00103:在预期以下情况之一时遇到符号“END”