Как импортировать PDF в таблицу с колонкой BLOB
Возник вопрос, как проще всего импортировать PDF в колонкуBLOB?
Думал реализовать такую логику : импортировать BLOB во временную таблицу (процедурой ниже), а потом, чтобы добавить BLOB в поле исходной таблицы сделать что-то такое:
UPDATE My_table SET blob=(select blob_pdf from temp_table) where rownum=1;
Пробовал следующим образом, но как по мне это слишком костыльно. И как оказалось, на работе нет прав на создание директории (1-ая строка). Сам скрипт:
CREATE OR REPLACE DIRECTORY BLOB_DIR AS 'C:\\';
CREATE TABLE tab1 (
id NUMBER,
blob_data BLOB
);
DECLARE
l_bfile BFILE;
l_blob BLOB;
l_dest_offset INTEGER := 1;
l_src_offset INTEGER := 1;
BEGIN
INSERT INTO tab1 (id, blob_data)
VALUES (1, empty_blob())
RETURN blob_data INTO l_blob;
l_bfile := BFILENAME('BLOB_DIR', 'smth.pdf');
DBMS_LOB.fileopen(l_bfile, DBMS_LOB.file_readonly);
-- loadfromfile deprecated.
-- DBMS_LOB.loadfromfile(l_blob, l_bfile, DBMS_LOB.getlength(l_bfile));
DBMS_LOB.loadblobfromfile (
dest_lob => l_blob,
src_bfile => l_bfile,
amount => DBMS_LOB.lobmaxsize,
dest_offset => l_dest_offset,
src_offset => l_src_offset);
DBMS_LOB.fileclose(l_bfile);
COMMIT;
END;
Ответы (3 шт):
У Oracle не очень хорошо со встроенными средствами загрузки BLOB. На сервере можно напрямую читать файлы с диска. Единственное ограничение это необходимость создания объектов DIRECTORY, большинстово админов (с которыми я общался) считают это угрозой беспоастности.
Сами функции по загрузке в какой-то степени будут похожи на представленную.
Чаще загружать файлы требуется с клиента, и если не хочется писать отдельную прогу (что правильно), то единственый способ использовать SQL*Loader. Почему то редко пишут, что SQL*Loader умеет это делать, хотя можно грузить как один файл, так и пачкой.
Примерные шаги по загрузке списка файлов.
Создаем таблицу
CREATE TABLE my_table
(id NUMBER,
author VARCHAR2(30),
created DATE,
text CLOB
);
Имеем два файла
file1.txt: Тестовый файл
file2.txt: Еще один файл
Создаем файл с описание (control file)
LOAD DATA
INFILE 'loader.csv'
INTO TABLE my_table
FIELDS TERMINATED BY ','
( id CHAR(10),
author CHAR(30),
created DATE "YYYY-MM-DD" ":created",
fname FILLER CHAR(80),
text LOBFILE(fname) TERMINATED BY EOF
)
Файл loader.csv содержит как поля, так и путь к файлу
1,John Smith,2015-04-29,file1.txt
2,Pete Jones,2013-01-31,file2.txt
Запускаем
sqlldr roger/roger control=loader.ctl log=loader.log bad=loader.bad
Пишу по памяти, могут быть ошибки.
как оказалось на работе нет прав на создание директории
Создавать директорию не обязательно. Посмотреть доступные директории можно запросом:
select * from all_directories;
Если таковых нет, или нет прав на перенос файлов в эти директории на системном уровне, то вам запрещено загружать с файловой системы сервера. В этом случае, лучше обратиться к администраторам БД, чем искать обходные пути этого запрета.
Если подходящая директория есть, обычно DATA_PUMP_DIR, то подход как в вопросе вполне стандартный и рекомендуемый.
Можно даже немного "приукрасить", например:
create or replace function blobLoader (filename varchar2) return blob is
bf bfile := bfilename ('TEMPFILES', filename);
bl blob;
begin
dbms_lob.createtemporary (bl, true);
dbms_lob.fileopen (bf, dbms_lob.file_readonly);
dbms_lob.loadfromfile (bl, bf, dbms_lob.getlength (bf));
dbms_lob.fileclose (bf);
return bl;
end;
/
create table tblob (id number, memo varchar2 (64), doc blob);
insert into tblob values (1, 'test blob load', blobLoader ('test.pdf'));
1 row inserted.
Результат:
select memo, dbms_lob.getlength (doc) bloblen from tblob t;
MEMO BLOBLEN
---------------- ----------
test blob load 300877
Альтернативный путь, загружать с локальной файловой системы используя SQL*Loader.
Здесь только ссылка на оф. документацию, т.к. ответ с примером дал @Alex R..
Если надо вставить или изменить только небольшое кол-во записей из файлов на локальной файловой системе, то проще воспользоваться SQL Developer (поставляется в "коробке").
Выберите в проводнике слева ранее созданую таблицу, в примере:
create table tblob (id number, memo varchar2 (64), doc blob);
И далее, при добавлении или изменении записей, редактируйте значения BLOB колонки в диалоговом окне - Edit Value. Последовательность действий и назначение кнопок интуитивно и не нуждается в отдельном пояснении.
После фиксации изменений кнопкой F11, в окне сообщений появятся лог произведённых изменений:
INSERT INTO "SH"."TBLOB" (ID, MEMO, DOC) VALUES ('1', 'Man. load', empty_blob())
UPDATE "SH"."TBLOB" SET DOC=? WHERE ROWID=:sqldevrowid AND ORA_ROWSCN=:sqldevrowscn
Commit Successful
