Как исправить ошибку PLS-00103 в функции почтового индекса? - PullRequest
1 голос
/ 03 апреля 2019

Итак, я создал функцию для определения наличия почтового индекса в таблице. У меня есть таблица с именем "ZIPCODE" и столбец с именем "ZIP". Для этой функции я хочу, чтобы она возвращала логическое значение true или false независимо от того, существует почтовый индекс или нет. Тем не менее, я получаю эту ошибку:

PLS-00103: Обнаружен символ «13501» при ожидании одного из следующих действий: (начинайте регистр, объявляйте выход для goto, если loop mod null pragma поднимает return select update, в то время как с

Таким образом, проблема возникает после того, как я ввел почтовый индекс.

CREATE OR REPLACE FUNCTION zip_existence 
RETURN number IS

bool number (2) := 0;

BEGIN
    &zip_input;

     FOR record_current_zip IN current_zip LOOP
        IF record_current_zip = zip_input THEN
            bool := 0;
                DBMS_OUTPUT.PUT_LINE('Zipcode in use!');
        IF record_current_zip != zip_input  THEN
            bool := 1;
                DBMS_OUTPUT.PUT_LINE('Zipcode not in use');
                END IF;
            END IF;
        RETURN boolean; 
    END loop;
END; 

1 Ответ

3 голосов
/ 03 апреля 2019

&zip_input - это переменная подстановки клиента, которая оценивается при компиляции функции, что вряд ли будет тем, что вам нужно.Где бы вы ни использовали, это все равно не имеет смысла, и более поздние немного больше логических ссылок не имеют префикса &.Итак, в данный момент вы, кажется, делаете:

define zip_input = 13501;

CREATE OR REPLACE FUNCTION zip_existence 
RETURN number IS

bool number (2) := 0;

BEGIN
    &zip_input;

     FOR record_current_zip IN current_zip LOOP
....
END; 
/

, который действительно получает PLS-00103: Encountered the symbol "13501"..., потому что он расширен до:

CREATE OR REPLACE FUNCTION zip_existence 
RETURN number IS

bool number (2) := 0;

BEGIN
    13501;

     FOR record_current_zip IN current_zip LOOP
...

и что 13501 не принадлежит

Вы должны передать значение, которое вы хотите проверить, в качестве формального аргумента функции:

CREATE OR REPLACE FUNCTION zip_existence (zip_input zipcode.zip%TYPE)
RETURN number IS
  bool number (1) := 0;
BEGIN
...

Но есть и другие проблемы

  • вывы используете курсор current_zip, который вы не определили;
  • в этом цикле вы сравниваете

    IF record_current_zip = zip_input THEN
    

    , который ссылается на запись вместо поляв записи, так что это должно быть

    IF record_current_zip.zip = zip_input THEN
    
  • , тогда у вас есть второй IF в пределах первого, который имеет ту же проблему поля, но большеважно то, что никогда не может быть истиной - вы действительно хотите, чтобы это было ELSE, я думаю;

  • также внутри цикла, который вы собираетесь установить bool в ноль, когда вы найдете совпадение, но он все равно начинается с нуля, и даже если вы исправите проблему IF, вы вернетесь на основе первой записиполучить от курсора.Похоже, что вы хотите перебрать все возможные почтовые индексы - но вы этого не сделаете, и если вы это сделали (вернувшись позже), вы бы продолжали перезаписывать этот bool результат;
  • , чтобы вы могли начать сbool установить в состояние "не найдено", и только изменить, если вы найдете совпадение;
  • ваш return имеет boolean (что является PL / SQLtype) вместо bool (ваша переменная).

Так что одним из способов сделать это может быть что-то вроде:

CREATE OR REPLACE FUNCTION zip_existence (zip_input zipcode.zip%TYPE)
RETURN number IS
  bool number (1) := 1; -- start with not-found state
  cursor current_zip is
    select * from zipcode;
BEGIN
  FOR record_current_zip IN current_zip LOOP
    IF record_current_zip.zip = zip_input THEN
      bool := 0;
    END IF;
  END loop;

  -- debugging only - client may not see this
  IF bool = 0 THEN
    DBMS_OUTPUT.PUT_LINE('Zipcode in use!');
  ELSE
    DBMS_OUTPUT.PUT_LINE('Zipcode not in use');
  END IF;

  RETURN bool; 
END; 
/

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

CREATE OR REPLACE FUNCTION zip_existence (zip_input zipcode.zip%TYPE)
RETURN number IS
  bool number (1);
BEGIN
  select case when count(*) > 0 then 0 else 1 end
  into bool
  from zipcode
  where zip = zip_input;

  -- debugging only - client may not see this
  IF bool = 0 THEN
    DBMS_OUTPUT.PUT_LINE('Zipcode in use!');
  ELSE
    DBMS_OUTPUT.PUT_LINE('Zipcode not in use');
  END IF;

  RETURN bool; 
END; 
/

Если ZIP не уникален, то вы можете воспользоватьсядобавление фильтра where rownum <= 1 к запросу.

...