Это ошибка в компиляторе PL / SQL? - PullRequest
14 голосов
/ 22 декабря 2010

В нашем 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;
/

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

РЕДАКТИРОВАТЬ 2 : JOTN, конечно, прав, и return IS переменная, и, кроме того, Компилятор не сообщает заранее, если переменная с тем же именем объявлена ​​дважды или более, вместо этого это среда выполнения.

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

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

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

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

Ответы [ 2 ]

9 голосов
/ 22 декабря 2010

Видимо, это позволяет использовать имя «возврат» в качестве переменной. В этом случае он объявляет переменную пакета. Я бы подумал, что это не удастся, потому что это ключевое слово, но я попробовал, и это сработало.

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

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

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

Теперь, если вы попытаетесь получить доступ к 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 
3 голосов
/ 22 декабря 2010

Просто хотел добавить дополнительную иллюстрацию, что ответ 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...