ORA-00984: 此处不允许列动态 sql

Posted

技术标签:

【中文标题】ORA-00984: 此处不允许列动态 sql【英文标题】:ORA-00984: column not allowed here dynamic sql 【发布时间】:2013-11-14 18:58:19 【问题描述】:

我试图在 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

出现...

【问题讨论】:

相关:Why cannot I use bind variables in DDL/SCL statements in dynamic SQL? 【参考方案1】:

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

其次,关于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;
/   

【讨论】:

您也可以使用using iid, dir, in_fname, out obj - 两者都可以,那么使用第二个returning 子句是否有优势? 谢谢,在我运行这个temp2:='img_'||temp||'.currval'; execute immediate 'UPDATE '||tablename||' SET icon = obj WHERE img_id = '||temp2;之后,序列不能在那里使用,序列名称在temp2中,它不是动态的,哪里出错了? @AlexPoole。 Alex,returning into 子句允许您将“record”返回到记录数据类型的变量中。您将无法使用 using 子句和 out-bind 变量来做到这一点。在这种特殊情况下(DML 语句没有返回“record”)对我来说确实没有明显的优势,除非您不必为绑定变量指定模式 (OUT),以防万一必须将多个值返回到多个外绑定变量中。【参考方案2】:

RETURNING INTO 子句应该在动态 DML 语句之外:

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

this documentation site about EXECUTE IMMEDIATE底部有一个例子

【讨论】:

看起来如此但不起作用,'因为返回不用于 dml。该语句会返回关于图标的错误,如果删除它,会出现以前的错误 @user2993505 对不起,我的错。【参考方案3】:

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

...
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 是否已填充。

【讨论】:

以上是关于ORA-00984: 此处不允许列动态 sql的主要内容,如果未能解决你的问题,请参考以下文章

SQL 错误:ORA-00984:此处不允许列

PL/SQL 错误:ORA-00984 此处不允许列

“命令行错误:1 列:698 错误报告 - SQL 错误:ORA-00984:此处不允许列

更改表,添加列 / ORA-00984:此处不允许列 PLSQL

操作Oracle数据库,插入数据时显示:ORA-00984列在此处不允许错误

00984. 00000 - “此处不允许列”