user4565864
user4565864

Reputation:

Why this PL/SQL doesn't work?

Im trying to learn PL/SQL. I am struck with this code. Please notify me where im going wrong. I use Oracle 10g in a command line .

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;
/

It shows

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

please notify me where i am going wrong.

Upvotes: 2

Views: 863

Answers (1)

Alex Poole
Alex Poole

Reputation: 191235

T.J. Crowder is sort of right, you shouldn't have a semicolon within a case statement in SQL, but this is the PL/SQL version so it's slightly different.

You are currently trying to assign the (non-existent) return from the dbms_output.put_line procedure (not function) call to your app variable.

For the assignment to work you need the case to evaluate to a string, so you can just use text literals; but the assignment needs to be in each branch:

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;
/

Which when run gets:

Enter value for v_grade: a
Grade b Appraisal: Excellent

PL/SQL procedure successfully completed.

Or use a query to do the assignment, though this is not quite as efficient:

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.

Or you can do the output directly in each branch:

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.

The first part of your output is before the case now.

You're basically mixing up the different approaches.

You might want to change the first line to:

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

... and then make the case look for A,B,C instead of a,b,c - then it won't matter what case the input is in.

You can read more about the PL/SQL case statemnt here and here.

Upvotes: 3

Related Questions