在预期以下情况之一时遇到符号“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:周二不提供香蕉。那有什么意义呢? (编辑:刚刚注意到您的评论我正在从一个网站尝试这个示例。我认为这不是一个很棒的网站。)
好的,我现在了解sqlcode
和sqlerrm
之间的区别。非常感谢您的意见!如果您能向我推荐一些可以帮助我在 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
更改为表中的列名,我猜这只是id
或c_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;但这会更加做作。
感谢您的意见! 当我更改以下行时,输出与预期一致:
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:在预期以下情况之一时遇到符号“)”