Календарь на Май 2024 года: calendar2008.ru/2024/may/
Навигация
Главная »  Sql 

USING - ключевое слово PL/SQL в версии 9i


Источник: ln
Эта статья посвящена двум особенностям работы PL/SQL-машины, которая в версиях 9.x объединена с SQL-машиной. Интересные особенности, которые могут всплыть при переносе программного обеспечения на новую версию сервера Oracle... По мотивам ответа Тома Кайта на вопросы, заданные 15 июня 2003 года. USING - ключевое слово PL/SQL! Том, Я хотел бы задать два вопроса, которые меня сильно сбивают с толку.
Первый вопрос: Один из разработчиков написал следующий код в Oracle 8.1.7.3:

create table auxtab as select from dual; create or replace procedure p_insert_auxtab as begin insert into auxtab using (select * from dual); commit; end; /  Procedure created.  SQL> show errors  No errors. 
При попытке выполнения тех же действий в версии 9.2.0.3.0 получаем сообщение об ошибке:

create table auxtab as select from dual; create or replace procedure p_insert_auxtab as begin insert into auxtab using (select * from dual); commit; end; /  Warning: Procedure created with compilation errors.  SQL> show errors  Errors for PROCEDURE P_INSERT_AUXTAB:  LINE/COL ERROR -------- ---------------------------------------------------- 3/1      PL/SQL: SQL Statement ignored 3/31     PL/SQL: ORA-00926: missing VALUES keyword 
Но если сделать так:

SQL> create or replace procedure p_insert_auxtab as 2  begin 3  insert into auxtab using select * from dual; 4  commit; 5* end; SQL> /  Procedure created.  SQL> show errors  No errors. 
Я никогда не думал, что слово "using" может использоваться так. Я использовал слово using в операторах типа execute immediate или при открытии курсора. Мой вопрос: правильно ли использовать слово using в операторе "insert into..."? Почему разработчик смог скомпилировать и выполнить процедуру в версии 8i со скобками, а в версии 9i это уже не прошло?

Второй вопрос: Один из разработчиков сделал следующее в версии 8.1.7.3

SQL> create table test2 2  (colnum number) 3  ;  Table created.  SQL> create or replace procedure p_test2 as 2  x number:=0; 3  begin 4    select colnum into x from test2 where colnum mod 4 =0; 5    dbms_output.put_line(to_char(x)); 6* end; SQL> /  Procedure created.  SQL> show error  No errors. 
В версии 9i я получаю:

SQL> create table test2 2  (colnum number) 3  ;  Table created.  SQL> create or replace procedure p_test2 as 2  x number:=0; 3  begin 4    select colnum into x from test2 where colnum mod 4 =0; 5    dbms_output.put_line(to_char(x)); 6* end; 7  /  Warning: Procedure created with compilation errors.  SQL> show errors  Errors for PROCEDURE P_TEST2:  LINE/COL ERROR -------- ----------------------------------------------------------------- 4/1      PL/SQL: SQL Statement ignored 4/59     PL/SQL: ORA-00920: invalid relational operator 
Почему версия 8i позволяла использовать функцию mod как оператор? Не должна ли былап выдаваться ошибка и в версии 8i? Я просмотрел документацию Oracle и не нашел ни одного примера, где mod используется как оператор. Можно ли использовать mod как оператор? Почему процедура перестала успешно компилироваться в версии 9i?

Ответ Тома Кайта

Первый вопрос:

insert into T (select * from dual); 
Такой оператор вас не удивляет, перавда? Так что:

insert into T T1 (select * from dual); 
тоже не удивит. А дальше:

insert into T "using" (select * from dual); 
Это ведь аналогичная конструкция, как и:

insert into T using (select * from dual); 
USING - всего лишь "корреляционное имя", ПСЕВДОНИМ таблицы T, а не ключевое слово. Но в версии 9i появилось ключевое слово USING в языке PL/SQL, что усложнило ситуацию:

ops$tkyte@ORA920> create table t as select * from dual where 1=0;  Table created.  ops$tkyte@ORA920> begin 2          insert into t using (select * from dual); 3  end; 4  /  end; * ERROR at line 3: ORA-06550: line 2, column 16: PL/SQL: ORA-00926: missing VALUES keyword ORA-06550: line 2, column 2: PL/SQL: SQL Statement ignored  ops$tkyte@ORA920> begin 2          insert into t using select * from dual; 3  end; 4  /  PL/SQL procedure successfully completed.  ops$tkyte@ORA920> begin 2          insert into t "using" (select * from dual); 3  end; 4  /  PL/SQL procedure successfully completed.  ops$tkyte@ORA920> begin 2          insert into t "using" select * from dual; 3  end; 4  /  PL/SQL procedure successfully completed. 
Но если коротоко -- USING интерпретировалось как псевдоним, а не как ключевое слово. Его просто не нужно указывать.

Второй вопрос:

Уникальная ситуация - я с такой не сталкивался. Проблема связана с тем, что в версиях до 8i включительно PL/SQL-машина использовала отдельный анализатор SQL. В PL/SQL все операторы типа =, < и т.п. определялись как "функции", они переписывались. Если включить sql_trace и посмотреть на SQL, сгенерированный из PL/SQL, можно увидеть следующее:

SELECT COLNUM FROM T  WHERE MOD (COLNUM,4) = 0 
Хотя в исходном коде и было написано:

ops$tkyte@ORA817DEV> create table t ( colnum number );  Table created.  ops$tkyte@ORA817DEV> insert into t select rownum-1 from all_users where rownum <=4;  4 rows created.  ops$tkyte@ORA817DEV> create or replace procedure p_test2 as 2     x number:=0; 3  begin 4     select colnum into x from t where colnum mod 4 =0; 5     dbms_output.put_line(to_char(x)); 6  end; 7  /  Procedure created.  ops$tkyte@ORA817DEV> exec p_test2;  0  PL/SQL procedure successfully completed.  ops$tkyte@ORA817DEV> select colnum from t where colnum mod 4 = 0; select colnum from t where colnum mod 4 = 0 * ERROR at line 1: ORA-00920: invalid relational operator 
Это нигде не описано в документации. Работало в 8i "случайно". Вот такие "странные, но интересные" особенности реализации...



 

 Symantec и VMware развивают сотрудничество в области решений для виртуализации.
 Различия глобального административного доступа и доступа к рабочему пространству в Rational Focal Point.
 Маленькие хитрости: автоматическое восстановление вида указателя курсора.
 Немного про Deadlock.
 API PHP в JavaScript. Краткий обзор PHP.JS.


Главная »  Sql 

© 2024 Team.Furia.Ru.
Частичное копирование материалов разрешено.