SQL 错误:ORA-00904:“CNPPARMID”:标识符无效

Posted

技术标签:

【中文标题】SQL 错误:ORA-00904:“CNPPARMID”:标识符无效【英文标题】:SQL Error: ORA-00904: "CNPPARMID": invalid identifier 【发布时间】:2016-10-15 18:04:50 【问题描述】:

我有一个函数:

在行立即执行'select' ||模式名 || '。' ||值1 || '_seq.nextval from dual' 转换为 cnpParmId;

出现 。 我尝试将 cnpParmId 放在引号内,尝试以所有可能的方式从对偶输入 cnpParmId。但它不起作用。 请给我一些想法来解决这个问题。 谢谢!!

【问题讨论】:

正如答案间接指出的那样,您可能在第二个execute immediate 语句中遇到错误,而不是第一个。 【参考方案1】:

使用execute immediate,你在函数范围之外执行语句,所以它不能使用PLSQL变量。我将通过将其作为普通查询执行并使用SELECT INTO 或游标来获取查询结果来解决此问题。

但如果您只是自己将值替换为查询字符串,它也应该可以工作,如下所示:

改变

'select ''T'' from dual where cnpParmId not in ' ||

进入

'select ''T'' from dual where ' || cnpParmId || ' not in ' ||

【讨论】:

【参考方案2】:

你的函数编译成功,运行时出现错误:

select test(user, 'T42') from dual;

SQL Error: ORA-00904: "CNPPARMID": invalid identifier
ORA-06512: at "MYSCHEMA.TEST", line 23

您说错误出现在第一个 execute immediate,但那是第 21 行而不是第 23 行,如果是 cnpParmId 引用它正在抱怨,那么它会导致编译错误 - 将创建函数但有错误/警告,并且无法调用它。

所以它是第 23 行的第二个 execute immediate,它在运行时出错(稍微重新格式化):

execute immediate
  'select ''T'' from dual where cnpParmId not in ' ||
  '(select value1 from ' || schemaname || '.' || tablename || ')'
  into good;

正如 GolezTrol 所说,动态语句是在不可见任何 PL/SQL 变量的 SQL 上下文中执行的。和运行生成的语句一样:

select 'T' from dual where cnpParmId not in (select value1 from myschema.t42);

...直接在 SQL*Plus 或 SQL Developer 中,也可以得到:

SQL Error: ORA-00904: "CNPPARMID": invalid identifier
00904. 00000 -  "%s: invalid identifier"

作为 GolezTrol 连接的变体,您可以使用绑定变量来防止每次循环进行硬解析,但您还需要提供主键列名称为 value1 也不会被识别;并且必须连接在:

execute immediate
  'select ''T'' from dual where :cnpParmId not in ' ||
  '(select ' || value1 || ' from ' || schemaname || '.' || tablename || ')'
  into good using cnpParmId;

编译并运行。

您也可以使用not exists 而不是not in,因为您正在寻找(索引)主键,所以它的性能可能会更好:

execute immediate
  'select ''T'' from dual where not exists (select null from '
  || schemaname || '.' || tablename || ' where ' || value1 || ' = :cnpParmId)'
  into good using cnpParmId;

您还可以将找到value1 的查询移到循环之外;重复调用没有任何好处。


看起来您正在这样做,因为您的主键值不是从序列中生成的。如果您仍在添加这样的新记录 - 例如通过仅在传递的键列为空时才使用序列的触发器 - 那么您需要像这样的 hack 或捕获 ORA-01001 的插入循环。但是这种方法仍然存在竞争条件 - 另一个会话可以同时使用您的函数找到的相同值执行手动插入,并且其中一个会话会出错。

使用序列通常会更好;如果您现在正在这样做,或者可以更改为这样做,那么一次性调整所有序列以高于当前最大键值会更简单。

【讨论】:

以上是关于SQL 错误:ORA-00904:“CNPPARMID”:标识符无效的主要内容,如果未能解决你的问题,请参考以下文章

SQL 错误:ORA-00904:“GENDER”:无效标识符 00904。00000 -“%s:无效标识符”

SQL 错误:ORA-00904: : 第 4 行中的标识符无效

SQL 错误:ORA-00904:创建表期间标识符无效

SQL 错误:ORA-00904:“CNPPARMID”:标识符无效

错误:PL/SQL:ORA-00904::标识符无效

SQL 错误 [904] [42000]:ORA-00904:“SPAREBOX”:无效标识符 [重复]