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 great
的 insert
语句正在执行 iid
、 dir
和 in_fname
解析为本地声明的变量。如果是动态执行的 insert
语句,那些 iid
, dir
解析为您尝试插入数据的表的列名,并且根本不允许放置您尝试的表的列名在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 字符串中的 iid
、dir
、in_fname
和 obj
引用是文字,因此它们被解释为列名。您应该使用绑定变量(如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的主要内容,如果未能解决你的问题,请参考以下文章
“命令行错误:1 列:698 错误报告 - SQL 错误:ORA-00984:此处不允许列
更改表,添加列 / ORA-00984:此处不允许列 PLSQL