ORA-00907 при динамическом создании представления в PL/SQL и использовании CLOB

Это одна из тех ситуаций, когда вы получаете бесполезное сообщение об ошибке от Oracle.

Моя ситуация такова: я динамически создаю представление в PL/SQL. Я создаю строку и использую EXECUTE IMMEDIATE для создания представления. Строка настолько длинная, что я использую CLOB для ее хранения.

Когда я запускаю приведенный ниже код в TOAD, я получаю бесполезный

ORA-00907: missing right parenthesis error. 

Создание представления вручную в TOAD (без EXECUTE IMMEDIATE) не вызывает проблем. Я чувствую, что длина строки является фактором здесь, поскольку я успешно создал представления с более короткими строками (а также с помощью to_char() вместо dbms_lob.substr(), однако to_char() работает только с меньшими clobs).

Общая длина строки составляет 13775. (Очевидно, я отредактировал строку ниже, где я строю строку.) Это база данных Oracle 10g в Linux.

declare
lv_sql CLOB;

begin
lv_sql := ' CREATE OR REPLACE FORCE VIEW my_view.....';

EXECUTE IMMEDIATE dbms_lob.substr(lv_sql, 14765, 1 );    
end;

person TrojanName    schedule 03.10.2011    source источник
comment
Вы должны уметь работать с varchar2, они могут быть до 32767 байт в pl/sql.   -  person Klas Lindbäck    schedule 03.10.2011
comment
@KlasLindbäck - спасибо за комментарий. Я уже пробовал это, но получаю ошибку ORA-06502: PL/SQL: числовая или значение ошибки.   -  person TrojanName    schedule 03.10.2011


Ответы (1)


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

Ответ AskTom здесь демонстрирует:

http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:6161200355268

Говорит:

Вы указали, что максимальная длина строки для немедленного выполнения составляет 32 КБ.

Мы используем немедленное выполнение для создания сгенерированных пакетов, и в настоящее время мы передаем его> 35000 символов.

путем немедленного выполнения v_myvc1 || my_vc2

vc1 и vc2 — это 32 тыс. переменных типа varchar2. чья общая длина в настоящее время

35000

Все на 8.1.7

Мой вопрос заключается в том, какова максимальная длина строки для немедленного выполнения, потому что я беспокоился, что она составляет 32 КБ, и мы уже преодолели ее, и я не уверен, когда я собираюсь ударить стену.

Том Кайт отвечает:

Последующие действия 5 марта 2003 г. - 18:00 Центральный часовой пояс:

интересно - никогда бы не подумал сделать это таким образом.

Кажется, это сработало — не упрется ли оно в стену? не уверен, я бы никогда не превысил 32k.

похоже, он может быть довольно большим:

ops$tkyte@ORA817DEV> declare   
2          l_str1 long := 'select /* ' || rpad( '*', 20000, '*' ) || ' */ * '; 
3          l_str2 long := 'from /* '   || rpad( '*', 15000, '*' ) || ' */ dual';
4          l_str3 long := '/* '   || rpad( '*', 32000, '*' ) || ' */ ';   
5          l_result dual.dummy%type;   
6  begin   
7          execute immediate l_str1||l_str2||l_str3||l_str3||l_str3||' d' into l_result; 
8          dbms_output.put_line( l_result );   
9  end;  
10  / 

Процедура PL/SQL успешно завершена.

Хотя это было в экземпляре базы данных Oracle 8i, я был бы очень удивлен, если бы в более поздних версиях была исключена возможность последовательного подключения переменных VARCHAR2. К сожалению, я не могу протестировать его, так как в данный момент у меня нет под рукой экземпляра весом 10 г.

person Ollie    schedule 03.10.2011
comment
большое спасибо за ответ. Однако я уже пробовал это, но получаю ошибку ORA-06502: PL/SQL: числовая или значение ошибки, поэтому я переключился на CLOB. - person TrojanName; 03.10.2011
comment
Вы использовали SUBSTR, когда использовали переменную VARCHAR2? - person Ollie; 03.10.2011
comment
Нет, просто немедленно выполните lv_sql; Интересно, выполняет ли немедленное выполнение какое-то переключение контекста, чтобы ограничение PL/SQL в 32 КБ больше не применялось? - person TrojanName; 03.10.2011
comment
Вопросы и ответы AskTom не предлагают (также EXECUTE IMMEDIATE можно использовать и для выполнения динамического PL/SQL). Не могли бы вы опубликовать точный SQL, который вы пытались запустить, чтобы получить ошибку? - person Ollie; 03.10.2011
comment
Кстати, я нашел статью, в которой у кого-то были проблемы с динамическим созданием представления с помощью EXECUTE IMMEDIATE, и все же, когда они запускали код создания представления через SQL * Plus, все было в порядке. В конце концов они решили проблему, удалив все ненужные скобки из кода представления, и все заработало нормально. Ваш код представления настолько прост, насколько это возможно? - person Ollie; 03.10.2011
comment
Супер, спасибо за информацию. Я думаю, что делаю некоторый прогресс. Мой тестовый код теперь работает в TOAD, когда я использую varchar2 (32767), и он фактически создает представление. Это здорово. Однако, когда я пытаюсь сделать то же самое в своем пакете PL/SQL, он все еще жалуется (с ошибкой ORA-06502: PL/SQL: числовая или значение ошибки) - person TrojanName; 03.10.2011
comment
Хорошо, теперь я чувствую, что хожу по кругу. Этот ORA-06502 возникает, когда я присваиваю длинную строку переменной lv_sql (даже несмотря на то, что длина lv_sql определена как 32 КБ). Я знаю, что длина этой строки всего 14 КБ. Именно по этой причине я предположил, что VARCHAR2 не может быть больше 4 КБ в моей версии Oracle, и почему я переключился на CLOB. - person TrojanName; 03.10.2011
comment
Попробуйте объединить несколько переменных VARCHAR2(32767) вместе и посмотрите, работает ли это. Возможно, вы используете кодировку, в которой используется более одного байта на символ. - person Ollie; 03.10.2011
comment
Успех! Я объявил lv_sql как VARCHAR2 (32767 CHAR), и это сработало. Спасибо за помощь! - person TrojanName; 03.10.2011
comment
Нет проблем, рад, что исправили. - person Ollie; 03.10.2011
comment
Если вы используете расширенное представление символов (например, UTF8), существует разница между VARCHAR2 (32767) и VARCHAR2 (32767 CHAR). Первый будет содержать 32767 байт, а второй — 32767 символов. - person Klas Lindbäck; 04.10.2011
comment
Клас, это то, что сделал ОП, чтобы обойти свою ошибку. Я подозреваю, что он использует UTF8 или аналогичную кодировку. - person Ollie; 04.10.2011