У меня есть процедура, в которой я пытаюсь написать исходный код (1290 строк) в dbms_output следующим образом:
dbms_output.put_line(DBMS_METADATA.GET_DDL('FUNCTION', 'name', 'owner')); --MYPROC, line 6
Я получаю :
ORA-06502: PL/SQL: numeric or value error
ORA-06512: in "MYPROC", line 6
. Эта ошибка возникает в toad. Я могу выполнить на вкладке редактора жабы:
SELECT DBMS_METADATA.GET_DDL('FUNCTION', 'name', 'owner') FROM DUAL;
Я имею в виду, что получаю исходный код в «Сетке данных».
То же самое происходит, когда я пытаюсь сохранить код в переменной CLOB:
src CLOB;
...
src := DBMS_METADATA.GET_DDL('FUNCTION', 'name', 'owner') ; --MYPROC, line 6
Любая подсказка?
Вам не ясно, что произойдет, если вы запустите последние две команды. Ошибку легко объяснить на первом, dbms_output ограничен 32 КБ (раньше было 255 байт, но, к счастью, это было снято). Со вторыми двумя должно быть все в порядке. Не могли бы вы опубликовать точное сообщение об ошибке, которое каждый из них дает вам?
То, что вы говорите, не может быть правдой. DBMS_OUTPUT.PUT_LINE
нельзя использовать на уровне SQL, он относится к PL/SQL.
MYPROC
и что он содержит в строке №6?Ошибка числа или значения обычно связана с тем, что вы пытаетесь сохранить «большие» значения в «маленькой» переменной:
SQL> declare
2 l_var varchar2(2);
3 begin
4 l_var := 'ABC';
5 end;
6 /
declare
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at line 4
SQL>
что, я полагаю, ты и сделал.
Другая причина - неправильно объявленная переменная, например.
SQL> declare
2 l_var number;
3 begin
4 l_var := 'A';
5 end;
6 /
declare
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character to number conversion error
ORA-06512: at line 4
SQL>
Я попытаюсь угадать, что вы можете делать:
SQL> set serveroutput on
SQL> DECLARE
2 src CLOB;
3 BEGIN
4 src := DBMS_METADATA.GET_DDL ('PACKAGE', 'MY_PKG', 'SCOTT');
5 DBMS_OUTPUT.put_line ('len = ' || DBMS_LOB.getlength (src));
6 END;
7 /
len = 67239
PL/SQL procedure successfully completed.
SQL>
Как видите, у меня работает нормально. Пакет не такой уж и маленький (смотрите его длину), так что - не могу сказать, что вы сделали не так. Я предлагаю вам сделать то же самое, что и я: скопировать/вставить код, который я разместил выше (эти 7 строк), исправить информацию (функция, ее имя, владелец) и опубликовать результат, отредактировав исходный вопрос, а не как комментарий.
Действительно, я внес исправления и добавил больше информации в свой вопрос.
Я тоже так сделал; Посмотрите, пожалуйста.
Из документации для dbms_output:
Максимальный размер строки составляет 32767 байт.
Это означает, что вы не можете передать больше за один вызов put_line
. В настоящее время вы передаете весь свой CLOB, который при 1290 строках, вероятно, превысит этот предел. И ошибка, которую вы получаете, когда вы это делаете, это «ORA-06502: PL/SQL: ошибка числа или значения», как вы видите.
Вы можете разделить свой CLOB на более мелкие фрагменты, и, поскольку он уже состоит из нескольких строк, имеет смысл сделать каждый фрагмент отдельной строкой из DDL. Вы можете сделать это, ища символы новой строки, извлекая весь текст до следующего и печатая его. Вам нужно несколько переменных, чтобы отслеживать, где вы находитесь. Что-то вроде этого должно работать для вас:
declare
src clob;
src_length pls_integer;
pos pls_integer := 1;
buffer varchar2(32767);
amount pls_integer := 32767;
begin
src := dbms_metadata.get_ddl('FUNCTION', 'TEST_FUNCTION_1', user);
src_length := dbms_lob.getlength(src);
while pos < src_length loop
-- read to next newline if there is one, rest of CLOB if not
if dbms_lob.instr(src, chr(10), pos) > 0 then
-- see how many charcaters there are until next newline
amount := dbms_lob.instr(src, chr(10), pos) - pos;
-- if there are any, read them into the buffer; otherwise clear it
if amount > 0 then
dbms_lob.read(src, amount, pos, buffer);
else
buffer := null;
end if;
pos := pos + amount + 1; -- skip newline character
else
-- no newline so read everything that is left
amount := 32767;
dbms_lob.read(src, amount, pos, buffer);
pos := pos + amount;
end if;
dbms_output.put_line(buffer);
end loop;
end;
/
Это не сработает, если у вас есть одна строка (без новой строки в конце или без нее), размер которой превышает 32 КБ, что, надеюсь, не будет проблемой с DDL. (Вы могли бы справиться с этим, но это привело бы к добавлению дополнительных строк новой строки, что тоже было бы нехорошо.)
Вы сказали, что функция составляет 1290 строк, но сколько в ней символов - если она больше 32 КБ, вам нужно разбить ее на более мелкие фрагменты. Вот так может быть.