Как импортировать 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 шт):

Автор решения: Alex R.

У 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

Пишу по памяти, могут быть ошибки.

→ Ссылка
Автор решения: 0xdb

как оказалось на работе нет прав на создание директории

Создавать директорию не обязательно. Посмотреть доступные директории можно запросом:

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..

→ Ссылка
Автор решения: 0xdb

Если надо вставить или изменить только небольшое кол-во записей из файлов на локальной файловой системе, то проще воспользоваться 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
→ Ссылка