у меня ошибка во время выполнения любое тело может проверить функцию и чего не хватает - PullRequest
0 голосов
/ 26 апреля 2018

Я создал функцию для проверки таблицы.

Если студент существует, вернуть Y.

У меня ошибка во время выполнения.

create or replace FUNCTION ssc_f_get_speical_need (P_STUDENT_NO IN NUMBER )
 RETURN char
 IS
 l_exist number ;
begin 


select s.STUDENT_NO  
into l_exist 
from SSC_WITH_SPECIAL_NEED  s
where s.STUDENT_NO = P_STUDENT_NO ;

if (l_exist = P_STUDENT_NO) then
return 'Y'  ;
else 
return 'N' ;
end if;
end;

Ответы [ 5 ]

0 голосов
/ 27 апреля 2018

Проверяя существование, независимо от того, используется ли первичный ключ или нет, я всегда следовал шаблону Тома Кайта для выбора из двойного, где существует.

create or replace function ssc_f_get_special_need
  (p_student_no in number)
  return char
is
  l_exist pls_integer;
begin
  select count(*)
  into l_exist
  from dual
  where exists
    (select s.student_no
     from ssc_with_special_need s
     where s.student_no = p_student_no);

  return case when l_exist = 1 then 'Y' else 'N' end;
end;
/
0 голосов
/ 26 апреля 2018

Поскольку STUDENT_ID, скорее всего, является столбцом первичного ключа, он не допускает дублирования, поэтому SELECT не может вернуть TOO_MANY_ROWS. С другой стороны, он может вернуть NO_DATA_FOUND, если параметр P_STUDENT_ID содержит значение, которого нет в таблице.

Простой способ исправить это - использовать агрегатную функцию (например, MAX в моем примере), которая будет возвращать

  • значение, если оно существует
  • NULL, если нет
  • но не вернет NO_DATA_FOUND, поэтому вам не нужно кодировать обработчик исключений

В целях тестирования я создал таблицу dummy на основе таблицы EMP Скотта.

create table ssc_with_special_need as
  select empno student_no from emp
  where rownum < 5;

Теперь функция:

create or replace function ssc_f_get_special_need
  (p_student_no in number)
  return char
is
  l_exist ssc_with_special_need.student_no%type;
begin
  select max(s.student_no)
    into l_exist
    from ssc_with_special_need s
    where s.student_no = p_student_no;

  return case when l_exist is not null then 'Y'
              else 'N'
         end;
end;
/

Тестирование:

SQL> select * from ssc_with_special_need;

STUDENT_NO
----------
      7369
      7499
      7521
      7566

SQL> select ssc_f_get_special_need(1)    result_1, --> doesn't exist in the table (return N)
  2         ssc_f_get_special_need(7369) result_2  --> exists in the table (return Y)
  3  from dual;

RESULT_1   RESULT_2
---------- ----------
N          Y

SQL>

Лучшим (правильным) способом является обработка возможных исключений; как я уже сказал, я не буду обрабатывать TOO_MANY_ROWS, так как его не следует поднимать, если STUDENT_ID является столбцом первичного ключа.

create or replace function ssc_f_get_special_need
  (p_student_no in number)
  return char
is
  l_exist ssc_with_special_need.student_no%type;
begin
  select s.student_no
    into l_exist
    from ssc_with_special_need s
    where s.student_no = p_student_no;
  -- if the above SELECT returned a value, return 'Y' immediately    
  return 'Y';
exception
  when no_data_found then
    -- SELECT didn't find a value and raised an exception - return 'N'
    return 'N';
end;
/

Тестирование: результат точно такой же:

SQL> select ssc_f_get_special_need(1)    result_1,
  2         ssc_f_get_special_need(7369) result_2
  3  from dual;

RESULT_1   RESULT_2
---------- ----------
N          Y

SQL>

Я бы не стал использовать WHEN OTHERS, так как это, вообще говоря, вредная привычка: обрабатывать то, что вы ожидаете, позвольте Oracle поднять все остальное (и обработать это позже, если необходимо).

0 голосов
/ 26 апреля 2018

Возможно, вы получите сообщение об ошибке «данные не найдены», если нет ученика с данным номером студента. Попробуйте проверить табель, если есть хотя бы одна подходящая строка.

CREATE OR REPLACE FUNCTION ssc_f_get_speical_need (p_student_no IN NUMBER)
    RETURN CHAR
IS
    l_exist   NUMBER;
    l_count   NUMBER;
BEGIN
    SELECT   COUNT ( * )
      INTO   l_count
      FROM   ssc_with_special_need s
     WHERE   s.student_no = p_student_no;

    IF l_count > 0
    THEN
        SELECT   s.student_no
          INTO   l_exist
          FROM   ssc_with_special_need s
         WHERE   s.student_no = p_student_no;

        IF l_exist = p_student_no
        THEN
            RETURN 'Y';
        END IF;
    END IF;

    RETURN 'N';
END;
0 голосов
/ 26 апреля 2018

Добавьте исключение в вашу функцию, просто чтобы проверить, сохраняется ли ошибка, поэтому проблема в другом месте.

CREATE OR REPLACE FUNCTION....

BEGIN....

EXCEPTION WHEN OTHERS THEN --catch any error
RETURN 'E';

END

https://www.techonthenet.com/oracle/exceptions/when_others.php

0 голосов
/ 26 апреля 2018

Если вы хотите избежать исключений NO_DATA_FOUND или TOO_MANY_ROWS, то вы можете переписать запрос на что-то похожее на:

select decode(count(s.STUDENT_NO),0,'N','Y')
into l_result 
from SSC_WITH_SPECIAL_NEED  s
where s.STUDENT_NO = P_STUDENT_NO ;

Итак, ваша функция будет выглядеть так:

create or replace function ssc_f_get_speical_need(p_student_no in number )
  return char
is
  l_result varchar2(1) ;
begin
  select decode(count(s.student_no),0,'N','Y')
  into l_result 
  from ssc_with_special_need  s
  where s.student_no = p_student_no ;

  return l_result;
end;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...