Как я могу скопировать BLOB из параметра в локальную переменную в Oracle PL / SQL? - PullRequest
1 голос
/ 16 марта 2012

У меня есть подпрограмма Oracle PL / SQL, которая принимает BLOB в качестве параметра.BLOB содержит файл .jpg.Я хочу назначить параметр BLOB локальной переменной.Затем я хочу вставить (или обновить) столбец BLOB в таблицу BLOB varaible.

Я пробовал что-то вроде этого:

declare
  vATTACHMENT blob;
begin
  dbms_lob.createtemporary(vATTACHMENT, false, dbms_lob.session);
  dbms_lob.write(vATTACHMENT, dbms_lob.lobmaxsize, 1, :pATTACHMENT)); 

  -- do some stuff

  insert into attachments (attachment, file_name)
                   values (vATTACHMENT, vFILE_NAME);
end;

Но я получаю следующую ошибку:

ORA-06502: PL/SQL: numeric or value error
ORA-06512: at "SYS.DBMS_LOB", line 811
ORA-06512: at line 21

Я также пробовал прямое назначение, например vATTACHMENT := :pATTACHMENT;, но оно тоже не хочет работать.

Ответы [ 3 ]

1 голос
/ 17 марта 2012

Я думаю, что вы можете использовать DEFAULT в объявлении переменной, чтобы присвоить ей значение без использования оператора присваивания :=, например ::

declare
  vATTACHMENT blob DEFAULT :pATTACHMENT;
begin
  -- rest of your code...
1 голос
/ 17 марта 2012

Я могу получить точную ошибку только тогда, когда pAttachment является нулевым или пустым (проверено в 10.2.0.5).Если это не так, я получаю ORA-21560 вместо этого, так как ему не нравится lobmaxsize.Если я сделаю это вместо этого, все будет в порядке:

dbms_lob.write(vATTACHMENT, dbms_lob.getlength(:pATTACHMENT), 1, :pATTACHMENT));

Но из ваших комментариев у вас возникли проблемы со ссылками на переменную bind более одного раза, и по какой-то причине я не совсем понимаю, что вы не можете выполнять назначенияв PL / SQL как := неверно истолковано - что делает использование PL / SQL вообще непрактичным, я бы подумал.Мне немного неясно, запускаете ли вы это как анонимный блок прямо из вашего клиента;если так, может быть, вам следует рассмотреть вопрос о том, чтобы сделать это хранимой процедурой, чтобы избежать обеих этих проблем?Затем вы можете просто сделать:

vATTACHMENT := :pATTACHMENT;

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

Если вы застряли с таким запуском, вы можете воспользоваться переключением контекста и сделать:

select :pATTACHMENT into vATTACHMENT from dual;

Но это не идеально;если вы просто хотите сделать копию, почему вы не используете процедуры копирования ?

dbms_lob.copy(vATTACHMENT, :pATTACHMENT, dbms_lob.getlength(:pATTACHMENT));

..., которые все равно ломают ваши re-referencing-bind-variableограничение, но этот действительно понимает lobmaxsize:

dbms_lob.copy(vATTACHMENT, :pATTACHMENT, dbms_lob.lobmaxsize);

Вы все равно получите сообщение об ошибке (я думаю, что ORA-22994), если :pATTACHMENT пусто или равно нулю, так что вам нужно будет сделатьубедитесь, что это не до вызова блока или проверить внутри.

0 голосов
/ 16 марта 2012

Четвертый параметр для DBMS_LOB.WRITE должен быть либо RAW, либо VARCHAR2.Если я вас правильно понимаю, вы привязываете существующий BLOB к заполнителю :pATTACHMENT, поэтому вы передаете неправильный тип.

Зачем вам вообще нужно назначать временный BLOB??Мне кажется, что это должно работать:

insert into attachments (attachment, file_name)
               values (:pATTACHMENT, vFILE_NAME);

Например, это работает нормально:

DECLARE
  PROCEDURE insert_blob( p_blob BLOB) IS
  BEGIN
    INSERT INTO t_dave (b) VALUES (p_blob);
  END;
BEGIN
  insert_blob( empty_blob() );
END;
/
...