Это ошибка в компиляторе PL/SQL?

В нашем репозитории SVN-кода я столкнулся с спецификацией пакета, которая после удаление нескольких строк - сводится к

create or replace package tq84 as
    return varchar2(10);
end tq84;
/

Мне кажется, что такая спецификация не имеет большого смысла и поэтому не должен компилироваться вообще. Но, может быть, я не вижу очевидного, так: это действительно ошибка?

Для полноты:

me @ xxx.yyy.zz > select * from v$version;
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bi
PL/SQL Release 10.2.0.4.0 - Production
CORE    10.2.0.4.0      Production
TNS for IBM/AIX RISC System/6000: Version 10.2.0.4.0 - Productio
NLSRTL Version 10.2.0.4.0 - Production

Изменить: было высказано предположение, что в спецификации, приведенной выше return, не ключевое слово, а переменная (package-). Это, похоже, не так, поскольку следующие компиляции одинаково хороши:

create or replace package tq84 as

    return varchar2(10);
    return number;
    return date;

end tq84;
/

и, очевидно, компилятор должен сказать мне, что я объявляю одну и ту же переменную несколько раз.

EDIT 2: JOTN прав, конечно, и return является переменной, и, кроме того, компилятор не сообщает upfront, если переменная с тем же именем объявляется дважды или более, вместо этого это среда выполнения, которая делает.

Итак, имея в виду это, можно скомпилировать что-то вроде

create or replace package return as
  subtype return is varchar2(10);
end return;
/

create or replace package tq84 as

    constant constant 

    return . return := 'return';

    function function 

    return   return . return;

end tq84;
/

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

Итак, я думаю, это не ошибка компилятора, поскольку return допускается в качестве имени переменной, но потом, это спорно, если компилятор должен, по крайней мере, дать предупреждение, если переменная с тем же именем объявлен несколько раз.

Ответы

Ответ 1

По-видимому, он позволяет использовать имя "return" в качестве переменной. В этом случае он объявляет переменную пакета. Я бы предположил, что это провалится, потому что это ключевое слово, но я попробовал его, и это сработало.

Попробуйте этот код:

create or replace package tq84 as 
  return varchar2(10); 
  somevar varchar2(5); 
  somevar varchar2(5); 
end tq84; 
/ 

set serveroutput on 
BEGIN 
  tq84.return:='Test'; 
  dbms_output.put_line(tq84.return); 
END; 
/ 

Это показывает возврат как переменную и позволяет объявлять одну и ту же переменную другого имени более одного раза.

Теперь, если вы попытаетесь получить доступ к somevar, вы получите следующее:

PLS-00371: at most one declaration for 'TQ84.SOMEVAR' is permitted 

Поэтому, по-видимому, это задерживает проверку по какой-либо причине.

Я только узнал, как вы можете обнаружить эти проблемы во время компиляции. Добавьте это:

alter session set plsql_warnings = 'enable:all'; 

Этот код выше компилируется с этими предупреждениями:

LINE/COL ERROR 
-------- ----------------------------------------------------------------- 
1/1      PLW-05018: unit TQ84 omitted optional AUTHID clause; default 
         value DEFINER used 

2/3      PLW-06010: keyword "RETURN" used as a defined name 
4/3      PLW-05001: previous use of 'SOMEVAR' (at line 3) conflicts with 
         this use 

Ответ 2

Просто хотел добавить дополнительную иллюстрацию, что ответ JOTN верен. Мне кажется, что компилятор позволяет объявить несколько переменных с тем же именем, но, возможно, это побочный эффект того, как PL/SQL реализует перегрузку метода. Во время выполнения он вызывает ошибку, если имя было объявлено несколько раз.

В примере, подобном вашему первоначальному примеру, ясно, что return используется как имя переменной. Вы можете назначить и прочитать его значение, как показано ниже.

dev> set serveroutput on
dev> create or replace package test
  2  as
  3    return varchar2(10);
  4  end test;
  5  /

Package created.

dev> exec test.return := 'Hi!';

PL/SQL procedure successfully completed.

dev> exec dbms_output.put_line( test.return );
Hi!

PL/SQL procedure successfully completed.

dev> create or replace package test
  2  as
  3   return varchar2(10);
  4   return varchar2(20);
  5  end test;
  6  /

Package created.

dev> exec test.return := 'Hi!';
BEGIN test.return := 'Hi!'; END;

           *
ERROR at line 1:
ORA-06550: line 1, column 12:
PLS-00371: at most one declaration for 'TEST.RETURN' is permitted
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored