为啥这个 PL/SQL 不起作用?

Posted

技术标签:

【中文标题】为啥这个 PL/SQL 不起作用?【英文标题】:Why this PL/SQL doesn't work?为什么这个 PL/SQL 不起作用? 【发布时间】:2016-04-09 10:30:47 【问题描述】:

我正在尝试学习 PL/SQL。我对这段代码感到震惊。请通知我我哪里出错了。我在命令行中使用 Oracle 10g。

declare
grade char(1):='&v_grade';
app varchar(15);
begin
app:=case v_grade
when 'a' then
dbms_output.put_line('Excellent');
when 'b' then
dbms_output.put_line('Good');
else
dbms_output.put_line('Bad');
end case;
dbms_output.put_line('Grade'||grade||' Appraisal:'||app);
end;
/

显示

Enter value for v_grade: a
old   2: grade char(1):='&v_grade';
new   2: grade char(1):='a';
dbms_output.put_line('Excellent');
                                 *
ERROR at line 7:
ORA-06550: line 7, column 34:
PLS-00103: Encountered the symbol ";" when expecting one of the following:
. ( * % & = - + < / > at else end in is mod remainder not rem
when <an exponent (**)> <> or != or ~= >= <= <> and or like
LIKE2_ LIKE4_ LIKEC_ between || multiset member SUBMULTISET_
The symbol ";" was ignored.
ORA-06550: line 9, column 29:
PLS-00103: Encountered the symbol ";" when expecting one of the following:
. ( * % & = - + < / > at else end in is mod remainder not rem
when <an exponent (**)> <> or != or ~= >= <= <> and or like
LIKE2_ LIKE4_ LIKEC_ between ||
ORA-06550: line 11, column 28:
PLS-00103: Encountered the symbol ";" when expecting one of the following:
. ( * % & = - + < / > at end in is mod remainder not rem
<an exponent (**)> <> or != or ~= >= <= <> and or like LIKE2_
LIKE4_ LIKEC_ between || multiset

请通知我哪里出错了。

【问题讨论】:

我对 PL/SQL 一无所知,但我怀疑因为 put_linecase...when...then 内,所以在它不正确之后放置 ;。在 SQL 中,; 终止语句。您不想在那里终止该语句。该语句直到end case 之后才结束(并且您确实有一个;,这是合适的)。 【参考方案1】:

T.J. Crowder 是对的,在 SQL 的 case 语句中不应该有分号,但这是 PL/SQL 版本,所以略有不同。

您当前正尝试将来自dbms_output.put_line 过程(非函数)调用的(不存在的)返回分配给您的app 变量。

要使分配工作,您需要将 case 评估为字符串,因此您可以只使用文本文字;但是分配需要在每个分支中:

declare
  grade char(1):='&v_grade';
  app varchar(15);
begin
  case grade
    when 'a' then app:= 'Excellent';
    when 'b' then app:= 'Good';
    else app := 'Bad';
  end case;

  dbms_output.put_line('Grade '||grade||' Appraisal: '||app);
end;
/

运行时获取:

Enter value for v_grade: a
Grade b Appraisal: Excellent

PL/SQL procedure successfully completed.

或者使用查询来完成分配,虽然效率不高:

declare
  grade char(1):='&v_grade';
  app varchar(15);
begin
  select case grade
    when 'a' then 'Excellent'
    when 'b' then 'Good'
    else 'Bad'
  end case
  into app
  from dual;
  dbms_output.put_line('Grade '||grade||' Appraisal: '||app);
end;
/

Enter value for v_grade: b
Grade b Appraisal: Good

PL/SQL procedure successfully completed.

或者你可以直接在每个分支中做输出:

declare
  grade char(1):='&v_grade';
begin
  dbms_output.put('Grade '||grade||' Appraisal: ');
  case grade
    when 'a' then
      dbms_output.put_line('Excellent');
    when 'b' then
      dbms_output.put_line('Good');
    else
       dbms_output.put_line('Bad');
  end case;
end;
/

Enter value for v_grade: c
Grade c Appraisal: Bad

PL/SQL procedure successfully completed.

你的输出的第一部分现在在案例之前。

您基本上是在混淆不同的方法。

您可能希望将第一行更改为:

  grade char(1):= upper('&v_grade');

...然后让 case 寻找 A,B,C 而不是 a,b,c - 那么输入的 case 无关紧要。

您可以阅读有关 PL/SQL case statemnt here 和 here 的更多信息。

【讨论】:

我怀疑它没有价值,但正如我所说,我对 PL/SQL 一无所知,所以... :-) 我仍然在第 9 行第 7 列出现错误Enter value for v_grade: a old 2: grade char(1):='&amp;v_grade'; new 2: grade char(1):='a'; end case; * ERROR at line 9: ORA-06550: line 9, column 7: PLS-00103: Encountered the symbol "CASE" when expecting one of the following: * &amp; = - + ; &lt; / &gt; at in is mod remainder not rem &lt;an exponent (**)&gt; &lt;&gt; or != or ~= &gt;= &lt;= &lt;&gt; and or like LIKE2_ LIKE4_ LIKEC_ between || multiset member SUBMULTISET_ The symbol "CASE" was ignored. @AravindS - 是的,对不起,我正在执行你的任务并且没有注册你不能这样做。我已经更新了三个备选方案。 原来你可以做作业like this too。

以上是关于为啥这个 PL/SQL 不起作用?的主要内容,如果未能解决你的问题,请参考以下文章

为啥这个合并语句不起作用?

PL/SQL 语句的 SQL 查询不起作用

PL/SQL 正则表达式不起作用

我的 PL/SQL 过程异常似乎不起作用

过程中的 PL/SQL 游标不起作用

将表名作为参数传递时 PL/SQL 函数不起作用