Oracle SQL:为什么我的函数输出null?

3 sql oracle plsql

CREATE OR REPLACE FUNCTION get_status_by_member_id
(p_member_id NUMBER) 
RETURN CHAR
AS
  v_status CHAR(1);
BEGIN
  select status
  into v_status
  from members
  where member_id = p_member_id;
  if v_status is null then
    return v_status || 'N';
  else
     return v_status;
  end if;
END get_status_by_member_id;
Run Code Online (Sandbox Code Playgroud)

Ben*_*Ben 6

你的问题是由一个有时令人讨厌的Oracle怪癖引起的.即,如果在SQL中调用PL/SQL函数,则null返回错误,而不是其他任何内容.

如果我创建一个非常简单的表...

create table a ( b number, c varchar2(1) );
insert into a values (1,'Y');
Run Code Online (Sandbox Code Playgroud)

......和两个功能.一个没有异常处理

create or replace function tmp_ben_fn (PId number) return char is
   l_status varchar2(1);   
begin  

   select c
     into l_status
     from a
    where b = PId;

   return coalesce(l_status, 'N');

end;
/
Run Code Online (Sandbox Code Playgroud)

还有一个有异常处理的人.

create or replace function tmp_ben_fn2 (PId number) return char is
   l_status varchar2(1);   
begin  

   select c
     into l_status
     from a
    where b = PId;

   return coalesce(l_status, 'N');

   exception when no_data_found then
      return 'A';

end;
/
Run Code Online (Sandbox Code Playgroud)

然后,我们使用这两个函数来选择数据.请记住,我们只有一行,所以我们只期待YN返回:

SQL> -- Expected output Y
SQL> select tmp_ben_fn(1) from dual;

TMP_BEN_FN2(1)
-------------------------------------------------

Y

SQL> -- Expected output, Error no_data_found
SQL> -- as row 2 does not exist.
SQL> select tmp_ben_fn(2) from dual;

TMP_BEN_FN(2)
-------------------------------------------------



SQL> -- Expected output, the same as tmp_ben_fn
SQL> select tmp_ben_fn2(2) from dual;

TMP_BEN_FN2(2)
-------------------------------------------------

A

SQL>
Run Code Online (Sandbox Code Playgroud)

正如您在函数中看到的那样,没有错误处理,当发生no_data_found异常时null返回.当我们捕获异常时,我们得到预期的A.

我怀疑member_id你想要选择的东西不存在.

作为一般规则:始终要知道何时可能发生异常,这select into...是一个特别令人担忧的例子,有机会选择太多而没有行.如果您的表格是唯一的,member_id那么您应该按如下方式更改您的功能:

CREATE OR REPLACE FUNCTION get_status_by_member_id (p_member_id NUMBER) 
RETURN CHAR IS
  v_status CHAR(1);
BEGIN
  select status
  into v_status
  from members
  where member_id = p_member_id;

  return v_status;

-- If the member_id does not exist
-- return N
exception when no_data_found then
   return 'N';
END get_status_by_member_id;
Run Code Online (Sandbox Code Playgroud)