鉴于PL / SQL函数看起来有点像:
Function f(pVar IN VARCHAR2) return VARCHAR2 IS
vs_ret VARCHAR2 := NULL;
BEGIN
select name into vs_ret from people where nickname = pVar;
return vs_ret;
END f;
如果people.nickname
没有唯一性约束,会发生什么?如果(当)两个人有相同的昵称时会发生什么 - 它会导致错误还是只返回语句返回的第一行的值?
这似乎是我正在调整的现有功能,因此选项仅限于更改所有内容。
答案 0 :(得分:3)
它将抛出预定义的TOO_MANY_ROWS
(ORA-01422
)异常。您可以像这样处理异常:
CREATE FUNCTION f(
pVar IN VARCHAR2
) RETURN VARCHAR2
IS
vs_ret VARCHAR2;
BEGIN
SELECT name
INTO vs_ret
FROM people
WHERE nickname = pVar;
RETURN vs_ret;
EXCEPTION
WHEN TOO_MANY_ROWS THEN
RETURN NULL; -- or you could do: RETURN 'Error: Too Many Rows';
WHEN NO_DATA_FOUND THEN
RETURN NULL; -- or you could do: RETURN 'Error: Not Found';
END f;
或者,您可以保留未处理的异常;在这种情况下,异常将被传递回调用块的层次结构,并且每个异常将有机会处理它,如果它仍然未处理,将使用ORA-01422: exact fetch returns more than requested number of rows
终止查询。
另一种方法是,如果您只想返回第一个名称而不管实际有多少匹配,则将AND ROWNUM = 1
添加到WHERE
查询的SELECT
子句中(这样返回的行永远不会超过一行 - 尽管仍然可以返回零行。
另一种选择,如果你真的想要返回多个值(或没有值),那就是使用BULK COLLECT INTO
和一个集合:
CREATE FUNCTION f(
pVar IN VARCHAR2
) RETURN SYS.ODCIVARCHAR2LIST
IS
vs_ret SYS.ODCIVARCHAR2LIST;
BEGIN
SELECT name
BULK COLLECT INTO vs_ret
FROM people
WHERE nickname = pVar;
RETURN vs_ret;
END f;
答案 1 :(得分:0)
不确定这对您是否有用,但在我不关心太多行或没有找到数据的情况下,我将其更改为光标。
在没有数据的情况下发现它没有进入循环,对于太多的行,它只是循环了很多次。
/* Formatted on 12/17/2015 8:18:33 AM (QP5 v5.115.810.9015) */
FUNCTION f (pVar IN VARCHAR2)
RETURN VARCHAR2
IS
vs_ret VARCHAR2 := NULL;
BEGIN
FOR c IN (SELECT name
FROM people
WHERE nickname = pVar)
LOOP
vs_ret := c.name;
END LOOP;
RETURN vs_ret;
END f;
答案 2 :(得分:0)
如果您在发生错误时知道有意义的事情,您可能会收到错误。
[echo] abc,123
[echo] abc,123
[echo] xyz,678
[echo] xyz,678
[echo] ijk,921
[echo] ijk,921
脚本输出
drop table people;
create table people (name varchar2(200), nickname varchar2(200));
insert into people values('name1','nick1');
insert into people values('name1','nick1');
select * from people;
create or replace function f(pVar IN VARCHAR2)
return VARCHAR2
IS
vs_ret people.name%type;
BEGIN
select name into vs_ret from people where nickname = pVar;
return vs_ret;
END f;
select f('nick1') from dual;
--- ==> error
create or replace function f(pVar IN VARCHAR2)
return VARCHAR2
IS
vs_ret people.name%type;
BEGIN
select name into vs_ret from people where nickname = pVar;
return vs_ret;
exception
when TOO_MANY_ROWS then
return null; -- This is no good solution but just to demo it
END f;
select f('nick1') from dual;
-- ==> null as Output