新手到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)我是否必须使用'&amp; my_inparam'语法引用输入参数?
3)如果我通过首先创建sql文本然后打开引用光标来接近这个,是否有用于连接字符串的快捷方式,如
sql_text &= ' and another_condition = 1'
答案 0 :(得分:6)
以相反的顺序...不,没有像&=
这样的连接的简写。您可以使用concat()
函数,但||
方法更常见,更方便,尤其是当您将两个以上的内容放在一起时 - 嵌套concat()
调用不是容易遵循。我坚持你正在做的事情。
其次,不,您将SQL * Plus替换变量与PL / SQL变量混淆。您对'&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,但在使用其他管理工具时可能无效 数据库对象。
您引用的程序名称属于此类别;所引用的变量名称也是如此。它们都是标识符,并且适用相同的建议。