ORACLE Пакетные операторы DDL в Execute Immediate - PullRequest
5 голосов
/ 07 августа 2009

Я пытаюсь запустить несколько операторов ddl в одном операторе Execute Immediate. Я думал, что это будет довольно просто, но, похоже, я ошибаюсь.

Идея такова:

declare v_cnt number; 

begin 

select count(*) into v_cnt from all_tables where table_name='TABLE1' and owner = 'AMS'; 

if v_cnt = 0 then 

execute immediate 'CREATE TABLE TABLE1(VALUE VARCHAR2(50) NOT NULL)  ALTER TABLE TABLE1 ADD (MYVAL2 NVARCHAR2(10))'; 

end if; 

end;

однако это приводит к ошибке

ORA-00911: недопустимый символ ORA-06512: в строке 10

Каждый из операторов в пакете работает нормально, если я выполняю их самостоятельно. и если я возьму этот оператор и выполню его, он будет работать нормально (с; между 2 операторами). Если я удалю; между утверждениями я получаю другую ошибку о недопустимой опции

план состоит в том, что я смогу построить таблицу, экспортировать схему таблицы для этой таблицы, включая все ее операторы alter, а затем запустить пакет для другой системы в рамках процесса установки / обновления.

Итак, как мне пакетировать эти операторы DDL в пределах одного выполнения немедленно? Или есть лучший способ сделать то, что мне нужно?

Я немного новичок в Oracle, должен признать. Спасибо всем за терпение.

Ответы [ 2 ]

4 голосов
/ 07 августа 2009

Точка с запятой не является частью синтаксиса SQL Oracle. SQL * Plus и другие инструменты на стороне клиента используют точку с запятой для обозначения конца оператора SQL, но сервер его не видит.

Мы можем заставить SQL * Plus передавать точку с запятой в БД:

SQL> set sqlterminator off
SQL> select * from user_tables;
  2  /
select * from user_tables;
                         *
ERROR at line 1:
ORA-00911: invalid character

Если я возьму этот оператор и выполню его, он будет работать нормально (с; между двумя операторами) Инструмент клиента, который вы используете, разбивает его на два обращения к БД.

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

Я полагаю, можно было бы вызвать execute немедленно со строкой, содержащей анонимный блок PL / SQL, с отдельными вызовами для немедленного выполнения внутри него ... и я не знаю, какой смысл это делать. ;)

2 голосов
/ 07 августа 2009

Зачем вам нужен один вызов EXECUTE IMMEDIATE? Конечно, просто сделать это как 2 звонка?

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

Кроме того, почему бы просто не настроить таблицу правильно при первом вызове? Вы могли бы сделать ...

CREATE TABLE TABLE1 (ЗНАЧЕНИЕ VARCHAR2 (50), НЕ НУЛЬ

... вместо 2 звонков.

Кроме того, вы смотрели на DBMS_METADATA ... он может генерировать DDL для таких объектов, как таблицы для вас.

...