在Oracle PL/SQL中,如何将BLOB从参数复制到局部变量?

在Oracle PL/SQL中,如何将BLOB从参数复制到局部变量?,oracle,plsql,oracle10g,blob,Oracle,Plsql,Oracle10g,Blob,我有一个oraclepl/SQL例程,它将BLOB作为参数。BLOB包含一个.jpg文件。我想将BLOB参数指定给一个局部变量。然后我想在BLOB变量表中插入(或更新)一个BLOB列 我试过这样的方法: declare vATTACHMENT blob; begin dbms_lob.createtemporary(vATTACHMENT, false, dbms_lob.session); dbms_lob.write(vATTACHMENT, dbms_lob.lobmaxsiz

我有一个oraclepl/SQL例程,它将BLOB作为参数。BLOB包含一个.jpg文件。我想将BLOB参数指定给一个局部变量。然后我想在BLOB变量表中插入(或更新)一个BLOB列

我试过这样的方法:

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

我也尝试过一个直接的任务,比如
vatachment:=:pATTACHMENT
但这也不起作用。

DBMS\u 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;
/

我认为您可以在变量声明中使用
DEFAULT
为其赋值,而无需使用赋值运算符
:=
,例如:

declare
  vATTACHMENT blob DEFAULT :pATTACHMENT;
begin
  -- rest of your code...

只有当
pAttachment
为null或空时(在10.2.0.5中测试),我才能得到准确的错误。如果不是,我会得到
ORA-21560
,因为它不喜欢
lobmaxsize
。如果我这样做,没关系:

dbms_lob.write(vATTACHMENT, dbms_lob.getlength(:pATTACHMENT), 1, :pATTACHMENT));
但是从您的评论来看,多次引用bind变量会出现一些问题,并且由于某种原因,我不太理解您不能在PL/SQL中执行赋值,因为
:=
被误解了,这使得使用PL/SQL有点不切实际,我想。我有点不清楚你是不是直接从你的客户那里以匿名的方式运行这个程序;如果是这样,也许你应该考虑把它作为一个存储过程来避免这两个问题?然后你可以做:

vATTACHMENT := :pATTACHMENT;
。。。尽管这样,它将是一个传递给过程的参数,而不是一个绑定变量,而且您不需要在一开始就同时使用副本(如Dave Costa所建议的)

如果您坚持这样运行,您可能会发生上下文切换并执行以下操作:

select :pATTACHMENT into vATTACHMENT from dual;
但这并不理想;如果你只是想复制,为什么不使用

。。。这样仍然打破了重新引用绑定变量的限制,但这一个确实理解了
lobmaxsize

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

如果
:pATTACHMENT
为空或null,您仍然会得到一个错误(我想是ORA-22994),因此您需要在调用块之前确保它不是空的,或者检查内部。

直接插入确实有效,但由于我正在使用的组件,我不能在PL/SQL中多次引用:pATTACHMENT参数,所以我想把它的值复制到一个局部变量。然后我可以根据需要经常引用它。当您尝试直接赋值时,具体的问题是什么?执行PL/SQL的组件的问题更多。它认为前面有冒号的任何东西都是一个参数,因此它创建了一个参数名“=”。我选择这个答案是因为它最简单,并且完全满足了我的需要:允许我在整个SQL中使用vATTACHMENT,只引用一次:pATTACHMENT。谢谢Alex。我的许多问题都源于我的环境。我在Delphi7中使用一个TADOCommand。我试图设计PL/SQL以适应该组件的一些特性。另外,我也尝试过dbms_lob.copy(在我看到您的答案之前),但我一定是把参数弄错了,因为我也无法让它工作+1了解您答案中的详细信息。
dbms_lob.copy(vATTACHMENT, :pATTACHMENT, dbms_lob.lobmaxsize);