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

ear*_*efl 2 oracle plsql stored-procedures syntax-error

新手到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;
Run Code Online (Sandbox Code Playgroud)

所以很明显我正在尝试返回一个查询结果,可选地通过我传入的任何参数进行过滤.我对于为什么违规行返回错误感到茫然 - 在之前的迭代中,我能够返回结果,但是现在,神秘地,它停止了工作.

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

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

3)如果我通过首先创建sql文本然后打开引用光标来接近这个,是否有用于连接字符串的快捷方式,如

sql_text &= ' and another_condition = 1'
Run Code Online (Sandbox Code Playgroud)

Ale*_*ole 6

以相反的顺序...不,没有连接的简写&=.您可以使用该concat()函数,但该||方法更常见,更方便,特别是如果您将两个以上的东西放在一起 - 嵌套concat()调用并不容易理解.我坚持你正在做的事情.

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

除了一些原因,你已经决定要难为自己和使用情况,sentisive程序和变量名,所以你不得不提到"my_inparam1",在双引号,随处可见.

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

OPEN "my_output" FOR sql_text;
Run Code Online (Sandbox Code Playgroud)

除非你有一个非常好的理由,否则真的不这样做.

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;
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请参阅命名规则:

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

带引号的标识符以双引号(")开头和结尾.如果使用带引号的标识符命名模式对象,则每次引用该对象时都必须使用双引号.

未加引号的标识符不包含任何标点符号.

更重要的是:

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

您引用的程序名称属于此类别; 所引用的变量名称也是如此.它们都是标识符,并且适用相同的建议.