PLSQL 过程中的查询必须返回 1 行,但返回更多行
Posted
技术标签:
【中文标题】PLSQL 过程中的查询必须返回 1 行,但返回更多行【英文标题】:Query in Procedure PLSQL must return 1 row, but return more rows 【发布时间】:2011-01-13 09:37:55 【问题描述】:我在实现 pl/sql 过程时遇到了一个奇怪的问题。 我的程序有四个 varchar 输入参数,并从表中提取一个 id 值,查询如下:
SELECT ID INTO idvar FROM TABLE T WHERE T.NAME = pn AND T.SUR = ln;
在此表中,name 和 sur 是唯一键。所以对于几个输入参数(pn,ln),我希望只获得一行,但事实并非如此。 确实,似乎只处理了第一个条件,而第二个没有。
在我的表中,这个测试行:
ID | NAME | SUR
1 | JO | SOME THING
2 | JO | OTHER ONE
3 | BO | SOME THING
如果在我的程序中我通过了
('JO', 'SOME THING')
我获得 ID:1 和 2。 但是如果我传递值
('BO', 'SOME THING')
我只获得 ID 3。
显然,在之前的查询中我得到了错误 ORA-01422,所以我先用游标定义替换它,然后用“for row in (query)”替换它:
CURSOR C IS
SELECT ID FROM TABLE T WHERE T.NAME = pn AND T.SUR = ln;
这种行为对我来说很奇怪,实际上如果我只执行来自 sqlplus 或 toad 的查询,我会得到正确的结果。
Oracle 版本是 8.1。
提前致谢
#这是我的程序(我希望你没有发现不匹配,因为我更改了对象的名称):
CREATE OR REPLACE PROCEDURE myproc (
pn in VARCHAR2,
ln in VARCHAR2,
other in VARCHAR2,
datarif in VARCHAR2
)
AS
idT NUMBER;
idST NUMBER;
idSE NUMBER;
CURSOR C IS
SELECT ID
FROM TABLE T
WHERE
T.NAME = pn AND T.SUR = ln;
BEGIN
for x in ( SELECT ID
FROM TABLE T
WHERE
T.NAME = pn AND T.SUR = ln )
loop
DBMS_OUTPUT.put_line('INFOR:' || x.ID);
end loop;
open C;
loop
fetch C into idT;
exit when C%NOTFOUND;
DBMS_OUTPUT.put_line('INLOOP:ID='||idT);
end loop;
close C;
DBMS_OUTPUT.put_line ( 'OUTLOOP: ID='||idT );
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
WHEN TOO_MANY_ROWS THEN
RAISE_APPLICATION_ERROR(-20001, 'Exact Fetch Returned many Rows');
WHEN OTHERS THEN
DBMS_OUTPUT.put_line('ERROR');
ROLLBACK;
RAISE;
END myproc;
/
谢谢
【问题讨论】:
你能贴出完整的过程和过程的调用(带上下文)吗? 我在原帖上写程序。 【参考方案1】:也许你的参数和表格的字段有冲突?
通过添加过程名称作为参数范围来更改它:
T.NAME = myproc.pn AND T.SUR = myproc.ln
【讨论】:
添加范围似乎是解决方案。非常感谢。【参考方案2】:“...因为我更改了对象的名称”
也许您的某些参数与某些列具有相同的名称。
例如,如果您的程序如下所示:
CREATE OR REPLACE PROCEDURE myproc (
pn in VARCHAR2,
sur in VARCHAR2,
other in VARCHAR2,
datarif in VARCHAR2
)
...
SELECT ID INTO idvar FROM TABLE T WHERE T.NAME = pn AND T.SUR = sur;
...
您会收到 TOO_MANY_ROWS 错误,因为条件“T.SUR = sur”与“T.SUR = T.SUR”的效果相同。
【讨论】:
【参考方案3】:我用您的示例表测试了您的第一条语句!在我的机器上它可以工作。但那是一个 Oracle 10g 数据库。
编辑: 我重新编写了您的程序,并且在我的机器上该版本运行良好!
create or replace
PROCEDURE myproc (
pn in VARCHAR2,
ln in VARCHAR2,
other in VARCHAR2,
datarif in VARCHAR2
)
AS
idvar NUMBER;
BEGIN
SELECT ID INTO idvar FROM TEST T WHERE T.NAME = pn AND T.SUR = ln;
DBMS_OUTPUT.put_line ( 'OUTLOOP: ID='||idvar );
END myproc;
【讨论】:
添加 ROWNUM=1 不是很好的建议。如果查询在不应该返回多行时,它可能表示编码错误(这似乎是每个接受的答案的情况)。因此,简单地通过“随机”选择其中一行来解决它并不是一个好的解决方案。 @Dave Costa:你是对的!我删除了肮脏的解决方案。但有时为了测试我会再次使用它......;)以上是关于PLSQL 过程中的查询必须返回 1 行,但返回更多行的主要内容,如果未能解决你的问题,请参考以下文章