1

我试图在 oracle 中运行这个 sql 脚本并得到一个错误

ORA-00984: 此处不允许列。

declare
  tablename varchar2(200):='imagesroom';
  temp varchar2(50):='room_id';
  iid number:=1;
  dir varchar2(200):='imgdirroom';
  in_fname varchar2(100):='img1.jpg';
  obj ORDIMAGE;
  ctx RAW(64) := NULL;
begin
  execute immediate 'INSERT INTO '||tablename||'('||temp||',extension,icon) 
  VALUES(iid,'''',ORDImage(''FILE'',upper(dir),in_fname)) 
  RETURNING icon INTO obj';
end;
/   

ERROR at line 1:
ORA-00984: column not allowed here
ORA-06512: at line 10

这个很好用

INSERT INTO imagesroom(room_id,extension,icon) 
VALUES(iid,'',ORDImage('FILE',upper(dir),in_fname)) 
RETURNING icon INTO obj;

它出什么问题了?

如果我这样做

execute immediate 'INSERT INTO :table(:type,extension,icon) 
VALUES(:id,'''',ORDImage(''FILE'',upper(:dir),:fname)) RETURNING icon INTO obj' 
using tablename,temp,iid,dir,in_fname;

然后

ERROR at line 1:
ORA-00903: invalid table name
ORA-06512: at line 10

出现...

4

3 回答 3

2

首先,为什么 PL/SQL 块中的第二个插入有效,而使用语句动态执行的几乎相同的插入execute immediate 无效?仅仅因为名称解析。当第二次插入时,insert您描述的那个语句this one works great正在执行iiddirin_fname解析为本地声明的变量。在动态执行insert语句的情况下,那些 iid解析dir 为您尝试插入数据的表的列名,并且根本不允许将您尝试插入的表的列名放入语句的value子句中insert。使用绑定变量。

其次,关于returning into子句。你需要其中两个。一个作为动态形成insert statement(动态returning into子句)的一部分,一个作为execute immediate语句(静态returning into子句)的一部分,以便通过插入语句返回值。或者,一个动态returning into子句和一个OUT绑定变量(在这种情况下)。

为此,您的匿名 pl/sql 块可能如下所示:

declare
  tablename  varchar2(200) :='imagesroom';
  temp       varchar2(50)  :='room_id';
  iid        number        :=1;
  dir        varchar2(200) :='imgdirroom';
  in_fname   varchar2(100) :='img1.jpg';
  obj        ORDIMAGE;
  ctx        RAW(64)       := NULL; -- really unnecessary, NULL by default.
  l_instr    varchar2(4000);
begin

  l_instr := 'INSERT INTO ' || tablename || '('||temp||',extension,icon) 
                VALUES(:1,'''',ORDImage(''FILE'',upper(:2), :3)) 
              RETURNING icon INTO :4';

  execute immediate l_instr 
    using iid, dir, in_fname  returning into obj;

end;
/   
于 2013-11-14T19:51:04.940 回答
1

RETURNING INTO子句应位于动态 DML 语句之外:

execute immediate 'INSERT INTO '||tablename||'('||temp||',extension,icon) 
  VALUES(iid,'''',ORDImage(''FILE'',upper(dir),in_fname))'
RETURNING icon INTO obj;

该文档站点底部有一个关于 EXECUTE IMMEDIATE的示例

于 2013-11-14T19:02:30.047 回答
1

您正在执行的 SQL 字符串中的iid、和引用是文字,因此它们被解释为列名。您应该使用绑定变量(如10g 文档中所示:dirin_fnameobj

...
begin
  execute immediate 'INSERT INTO '||tablename||'('||temp||',extension,icon) 
  VALUES(:iid,'''',ORDImage(''FILE'',upper(:dir),:in_fname)) 
  RETURNING icon INTO :obj'
  USING iid, dir, in_fname, OUT obj;
end;
/   

您可以添加类似

  dbms_output.put_line(obj.in_fname);

...以验证是否obj已填充。

于 2013-11-14T19:50:29.247 回答