Я хотел бы выполнить BULK копию с этим кодом, пожалуйста?
Я думаю, что этот сделает всю работу по записи всех файлов в каталог сразу, если я смогу преодолеть "ошибку недопустимой операции"
Ваша помощь, как всегда, очень ценится.
create or replace
PROCEDURE GetbFile
IS
l_output utl_file.file_type;
vstart NUMBER := 1;
bytelen NUMBER := 32000;
x NUMBER;
my_vr RAW(32000);
v_name VARCHAR2(32760);
BEGIN
FOR recFiles IN (SELECT dbms_lob.getlength(BLOB_VALUE) as len,
FILE_NAME,
BLOB_VALUE from Gfile)
LOOP
l_output := utl_file.fopen('THE_DIR', 'file_name'||'.dot', 'w', 32760);
IF recFiles.len < 32760 THEN
utl_file.put_raw(l_output, recFiles.BLOB_VALUE);
utl_file.fflush(l_output);
ELSE -- write in pieces
vstart := 1;
WHILE vstart < recFiles.len
LOOP
dbms_lob.read(recFiles.BLOB_VALUE, bytelen, vstart, my_vr);
utl_file.put_raw(l_output, my_vr);
utl_file.fflush(l_output);
-- set the start position for the next cut
vstart := vstart + bytelen;
-- set the end position if less than 32000 bytes
x := x - bytelen;
IF x < 32000 THEN
bytelen := x;
END IF;
END LOOP;
END IF;
End Loop;
dbms_output.put_line('End');
utl_file.fclose(l_output);
END GetFile;
1 ответ
Решение
- Почему вы заменили предыдущую версию кода этой версией? Если у вас уже есть версия кода, которая работает для записи одного большого двоичного объекта в файловую систему, очень просто вызвать этот код в цикле. Это также лучший способ разработки модульного кода.
- Когда вы получаете сообщение об ошибке, пожалуйста, опубликуйте стек ошибок. Это будет включать номер ошибки Oracle, сообщение об ошибке и номер строки ошибки. Скажите нам, какой строке соответствует ваш код (особенно, если есть различия в форматировании между тем, что вы публикуете здесь, и тем, какой код вы на самом деле выполняете).
- Вы не можете в одном потоке копировать каждый большой объект в файл одновременно. Один поток может делать одну вещь за раз, поэтому он может копировать один файл за раз. Вы можете выполнить цикл, чтобы копировать каждый файл последовательно. Мне все еще неясно, хотите ли вы именно этого или действительно хотите порождать 800 потоков, каждый из которых записывает один большой объект в файловую систему.
- Вам нужно закрыть файл внутри цикла, так как вы открываете файл в цикле (обратите внимание, что сохранение старого кода значительно облегчит предотвращение ошибок такого рода). И предполагая, что вы хотите использовать имя файла из таблицы, вы хотите использовать
recFiles.file_name
в вашем звонкеfopen
а не жестко запрограммированная строка 'имя_файла', которая будет пытаться записать каждый большой объект в один и тот же физический файл.
Учитывая это, я предполагаю, что вы хотите что-то подобное (обратите внимание, что было бы лучше использовать модульный код для этого кода, но, поскольку вы пытаетесь избежать этого, я предполагаю, что у вас есть для этого веские причины)
create or replace
PROCEDURE GetbFile
IS
l_output utl_file.file_type;
vstart NUMBER := 1;
bytelen NUMBER := 32000;
x NUMBER;
my_vr RAW(32000);
v_name VARCHAR2(32760);
BEGIN
FOR recFiles IN (SELECT dbms_lob.getlength(BLOB_VALUE) as len,
FILE_NAME,
BLOB_VALUE from Gfile)
LOOP
l_output := utl_file.fopen('THE_DIR', recFiles.file_name||'.dot', 'w', 32760);
IF recFiles.len < 32760 THEN
utl_file.put_raw(l_output, recFiles.BLOB_VALUE);
utl_file.fflush(l_output);
ELSE -- write in pieces
vstart := 1;
WHILE vstart < recFiles.len
LOOP
dbms_lob.read(recFiles.BLOB_VALUE, bytelen, vstart, my_vr);
utl_file.put_raw(l_output, my_vr);
utl_file.fflush(l_output);
-- set the start position for the next cut
vstart := vstart + bytelen;
-- set the end position if less than 32000 bytes
x := x - bytelen;
IF x < 32000 THEN
bytelen := x;
END IF;
END LOOP;
END IF;
utl_file.fclose(l_output);
End Loop;
dbms_output.put_line('End');
END GetFile;