Это ошибка в компиляторе 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