pl/sql 必须声明 PLS-00201 标识符

Posted

技术标签:

【中文标题】pl/sql 必须声明 PLS-00201 标识符【英文标题】:pl/sql PLS-00201 identifier must be declared 【发布时间】:2014-02-13 18:16:47 【问题描述】:

PL/SQL 新手。我有几个问题,下面是我正在尝试做的一个示例。

CREATE OR REPLACE PROCEDURE "my_procedure" (
   "my_inparam1"              IN     VARCHAR2,
   "my_inparam2"              IN     VARCHAR2,
   "my_output"                OUT SYS_REFCURSOR)
AS
   sql_text   VARCHAR2 (10000);
BEGIN
    sql_text :=
      'select something
       from my_table
       where 1 = 1';

   IF '&my_inparam1' <> 'foo'
   THEN
      sql_text := sql_text || ' and something = 0';
   END IF;

   IF '&my_inparam1' = 'foo' and '&my_inparam2' = 'bar'
   THEN
      sql_text := sql_text || ' and somethingelse = 1';
   ELSIF '&my_inparam1' = 'foo' AND '&my_inparam2' = 'baz'
   THEN
      sql_text := sql_text || ' and somethingelse = 0';
   END IF;

   OPEN my_output FOR sql_text; --ERROR PLS-00201 Identifier 'MY_OUTPUT' must be declared
END;

所以很明显我正在尝试返回一个查询结果,可以选择通过我传入的任何参数进行过滤。我不知道为什么有问题的行返回错误 - 在早期的迭代中,我能够返回结果,但现在,神秘地,它停止了工作。

1) 有没有更好的方法来解决这个问题?

2) 我是否必须使用 '&my_inparam' 语法来引用输入参数?

3) 如果我确实通过先创建 sql 文本然后打开 ref 游标来解决此问题,是否有连接字符串的快捷方式,例如

sql_text &= ' and another_condition = 1'

?

【问题讨论】:

FWIW - 双引号围绕变量名(或 Oracle 中的任何内容)使该名称为“CaSe SenSiTivE”,Oracle 中的默认大写为 UPPER_CASE,但如果您不使用双引号您可以将其输入为大写字母、大写字母、uPpEr_CaSe 或任何您喜欢的形式,数据库系统会为您将其转换为大写字母。 IMO 遵循的一个很好的规则是:永远,永远,永远不要在 Oracle 中对任何标识符进行双引号。 :-) 分享和享受。 【参考方案1】:

以相反的顺序...不,没有像&amp;= 这样的串联简写。您可以改用concat() 函数,但|| 方法更常见,也更方便,特别是如果您将两个以上的东西粘在一起 - 嵌套的concat() 调用并不容易遵循。我会坚持你正在做的事情。

其次,不,您将 SQL*Plus 替换变量与 PL/SQL 变量混淆了。您对'&amp;my_inparam1' 的引用应该是my_inparam1 等;没有和号,也没有引号。

除非出于某种原因,您决定让自己过得不愉快并使用区分大小写的过程和变量名称,因此您必须引用"my_inparam1",用双引号括起来,无处不在

这就是您收到消息PLS-00201 Identifier 'MY_OUTPUT' must be declared 的原因。您没有引用my_output,因此默认情况下它正在寻找一个不存在的名为MY_OUTPUT 的不区分大小写的变量。如果你这样做,它会起作用:

OPEN "my_output" FOR sql_text;

除非你有一个非常好的理由,否则真的不要那样做。

CREATE OR REPLACE PROCEDURE my_procedure (
   my_inparam1              IN     VARCHAR2,
   my_inparam2              IN     VARCHAR2,
   my_output                OUT SYS_REFCURSOR)
AS
   sql_text   VARCHAR2 (10000);
BEGIN
    sql_text :=
      'select something
       from my_table
       where 1 = 1';

   IF my_inparam1 <> 'foo'
   THEN
      sql_text := sql_text || ' and something = 0';
   END IF;
...
   OPEN my_output FOR sql_text;
END;

更多信息,请参考naming rules:

每个数据库对象都有一个名称。在 SQL 语句中,您表示 带有带引号的标识符或不带引号的对象的名称 标识符。

带引号的标识符以双引号 (") 开头和结尾。 如果您使用带引号的标识符命名架构对象,那么您必须 引用该对象时使用双引号。

不带引号的标识符不被任何标点符号包围。

更重要的是:

注意: Oracle 不建议对数据库对象名称使用带引号的标识符。这些引用的标识符被 SQL*Plus,但在使用其他管理工具时可能无效 数据库对象。

您引用的过程名称属于此类;引用的变量名也是如此。它们都是标识符,适用相同的建议。

【讨论】:

谢谢亚历克斯,是的,我通过实验发现a)输出参数上的双引号修复了我的错误,b)我不需要在输入参数上使用双引号任何一个。我剩下的问题都是简单的语法错误。

以上是关于pl/sql 必须声明 PLS-00201 标识符的主要内容,如果未能解决你的问题,请参考以下文章

在 PL/SQL 中出现错误“PLS-00201:必须声明标识符‘JSON_VALUE’”

PL/SQL 函数中的 XmlRoot、XmlElement、InsertChildXml 给出 PLS-00201 必须声明标识符

PLS-00201:标识符必须在过程中声明

ORA-06550:第 1 行,第 7 列:PLS-00201:必须声明标识符“PAYMENT_UPDATE” ORA-06550:第 1 行,第 7 列:PL/SQL:语句被忽略

PLS-00201 标识符必须声明为引用用户定义类型为 SYS

PLS-00201:必须声明标识符“ISDATE”