3
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;
4
  • 5
    FWIW - It's helpful if you give some context and your intuitions on the problem. Commented Aug 14, 2012 at 15:58
  • What is the type of member_id? Could there be duplicates in the table? In other words, perhaps the query is returning an error, so you are getting NULL because of a premature return and an undetected error. Commented Aug 14, 2012 at 16:08
  • 3
    can you update the question with desc members and a small snippet of output from select status,member_id from members;? Commented Aug 14, 2012 at 16:26
  • @Bianca, you said even if I do return 'N', it outputs null. it looks like your display code maybe the suspect. Commented Sep 21, 2012 at 22:15

2 Answers 2

6

Your problem is caused by a, sometimes, annoying quirk of Oracle. Namely that if a PL/SQL function is called in SQL and errors then null is returned, rather than anything else.

If I create a very simple table...

create table a ( b number, c varchar2(1) );
insert into a values (1,'Y');

... and two functions. One with no exception handling

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;
/

and one with exception handling.

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;
/

Then, we use these two functions to select the data. Remember we only have one row, so we're expecting only Y or N to be returned:

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>

As you can see in the function with no error handling, when a no_data_found exception occurs a null is returned. When we capture the exception, we get the expected A instead.

I suspect that the member_id you're trying to select does not exist.

As a general rule: Always be aware when an exception might occur, select into... being a particularly worrisome example with the opportunity to select both too many and no rows. If your table is unique on member_id then you should change your function as follows:

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;
Sign up to request clarification or add additional context in comments.

Comments

2

Try adding an exception handler to your code, as in:

CREATE OR REPLACE FUNCTION get_status_by_member_id 
  (p_member_id NUMBER) RETURN CHAR 
as 
  v_status CHAR(1); 
begin 
  BEGIN
    select status 
      into v_status 
      from members 
      where member_id = p_member_id;
  EXCEPTION
    WHEN NO_DATA_FOUND THEN
      v_status := NULL;
    WHEN TOO_MANY_ROWS THEN
      v_status := NULL;
  END;

  if v_status is null then 
    return 'N'; 
  else 
    return v_status; 
  end if; 
end get_status_by_member_id; 

This will handle the cases where there's no data which matches p_member_id, or where there are multiple rows which match p_member_id. This may or may not correct the issues you're seeing. It would be helpful if you would edit your post and add in the code you're using which calls get_status_by_member_id.

Share and enjoy.

2 Comments

In case there were NO DATA FOUND error in the SELECT the function call would have aborted and failed while performing the SELECT INTO. But in OPs case, it executes successfully but returns NULL. I agree with the exception handling part, but I also think that's not causing the issue here.
@Annjawn: my thinking is that if the function were called from a client program and return codes were not checked, etc, it's entirely possible that it could appear that the function executed correctly and returned NULL. That's about the only scenario I can picture where this function could 'return' NULL, and is why I tried wrapping an exception handler around the SQL.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.