У меня есть ошибка PLS-00103 в моем объявлении функции, и я не могу найти проблему - PullRequest
1 голос
/ 27 апреля 2019

В этом объявлении функции, по-видимому, есть некоторая ошибка компиляции, но я не могу найти, в чем дело. Все кажется нормальным. Функция выбирает примечания из таблицы и проверяет, все ли они превосходят 95, если это так, функция возвращает true.

Я попытался заменить первые '(' by ': =' и ')', как это было предложено, но это не сработало, как я ожидал ..

CREATE OR REPLACE FUNCTION BonnePerformance(codeP in CHAR(12), codeS in INTEGER)
RETURN VARCHAR2 IS
estBon VARCHAR2;
aNote INTEGER;
CURSOR allNote IS 
SELECT note
FROM Inscription
WHERE codePermanent = codeP AND codeSession = codeS;
BEGIN 
OPEN allNote;
FETCH allNote INTO aNote;
WHILE allNote%FOUND LOOP
IF aNote > 95 THEN
estBon := 'TRUE';
ELSE 
estBon := 'FALSE';
END IF;
FETCH allNote INTO aNote;
END LOOP;
CLOSE allNote;
RETURN estBon;
END;
/

Здесь ошибка

LINE/COL ERROR
-------- -----------------------------------------------------------------
1/40     PLS-00103: Encountered the symbol "(" when expecting one of the
         following:
         := ) , default varying character large
         The symbol ":=" was substituted for "(" to continue.

Ответы [ 2 ]

2 голосов
/ 27 апреля 2019

С моей точки зрения, вы делаете это неправильно (независимо от ошибок, которые вы получили при компиляции функции). Зачем? Потому что кажется, что функция должна возвращать ровно одно значение. Если это так, почему вы используете курсор (и цикл)? Если есть две (или более) строки, которые удовлетворяют условию, вы вернете только последнее выбранное значение, так что ... в чем смысл?

Поэтому я бы предложил что-то вроде этого:

  • выберите это единственное значение и верните результат
  • если ничего не найдено, обработайте его правильно, используя раздел EXCEPTION
    • другими словами, не «скрывайте» тот факт, что ни одна строка не удовлетворяет условию внутри цикла курсора. Не ленись. Пусть кто-нибудь еще, кто будет поддерживать ваш код когда-нибудь, узнает, что происходит. Вы не пишете загадочную книгу, а функцию

Вот что я имел в виду. Сначала тестовый пример:

SQL> create table inscription
  2    (codepermanent varchar2(10),
  3     codesession   int,
  4     note          number
  5    );

Table created.

SQL> insert into inscription
  2    select 'x', 1, 20 from dual union all
  3    select 'y', 2, 99 from dual;

2 rows created.

Функция:

SQL> create or replace function bonneperformance
  2    (codep in varchar2, codes in int)
  3  return varchar2
  4  is
  5    estbon varchar2(10) := 'UNKNOWN';
  6  begin
  7    select case when note > 95 then 'TRUE'
  8                else 'FALSE'
  9           end
 10    into estbon
 11    from inscription
 12    where codepermanent = codep
 13      and codesession = codes;
 14
 15    return estbon;
 16  exception
 17    when no_data_found then
 18      return estbon;
 19  end;
 20  /

Function created.

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

SQL> select bonneperformance('x', 1) result from dual;

RESULT
--------------------
FALSE

SQL> select bonneperformance('y', 2) result from dual;

RESULT
--------------------
TRUE

SQL> select bonneperformance('z', 3) result from dual;

RESULT
--------------------
UNKNOWN

SQL>
2 голосов
/ 27 апреля 2019

Ваш код выдает ошибку, поскольку длина (12) определена для параметра функции, который нарушен и должен быть удален как .. BonnePerformance(codeP in CHAR, codeS in INTEGER).Кстати, это хорошая привычка всегда использовать переменную строкового типа в качестве переменной длины.Итак, конвертируйте CHAR в VARCHAR2.

. Кроме того, у вас есть проблема с определением estBon локальной переменной как VARCHAR2 без длины.В этом случае параметру строкового типа требуется длина, например estBon VARCHAR2(100).Длина зависит от ваших потребностей.

Последний вопрос - это второе использование FETCH allNote INTO aNote; непосредственно перед END LOOP;.Вам не нужно использовать это снова.Так как вы уже использовали сразу после открытия курсора allNote выше.Итак, преобразуйте весь код в;

CREATE OR REPLACE FUNCTION BonnePerformance(codeP in VARCHAR2,
                                            codeS in INTEGER)
  RETURN VARCHAR2 IS
  estBon VARCHAR2(100);
  aNote  INTEGER;
  CURSOR allNote IS
    SELECT note
      FROM Inscription
     WHERE codePermanent = codeP
       AND codeSession = codeS;
BEGIN
  OPEN allNote;
  FETCH allNote
    INTO aNote;
  WHILE allNote%FOUND LOOP
    IF aNote > 95 THEN
      estBon := 'TRUE';
    ELSE
      estBon := 'FALSE';
    END IF;
  END LOOP;
  CLOSE allNote;
  RETURN estBon;
END;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...