概述
Starting with Oracle9i, PL/SQL supports the use of case statements and case expressions. These constructs are often convenient to use in place of complex if-then-else logic and function similarly to counterparts in other languages (e.g. the C switch statement).
Case statements are standalone statements that can appear anywhere any other PL/SQL statement can appear. Case expressions are similar to case statements, but return a value and can only appear in places where any other PL/SQL expression can appear. There are also some subtle syntax differences between case statements and expressions; the differences will be pointed out where appropriate in this article.
程序说明
以下所有程序均在windows xp 下Oracle 9.2.0.1上测试通过,所有的SQL均可以在SQL*PLUS或plsql dev中测试运行。
参考资料
PL/SQL User's Guide and Reference
程序
Sample 1:
A simple example demonstrating the proper syntax for a case statement
using a character variable as the selector. See the section entitled
'Restrictions' at the end of this article for details on which PLSQL
datatypes may appear as a selector in a case statement or expression.
- - - - - - - - - - - - - - - - Code begins here - - - - - - - - - - - - - - - -
set serveroutput on
declare
achar char(1) := '&achar';
begin
case achar
when 'A' then dbms_output.put_line('The description was Excellent');
when 'B' then dbms_output.put_line('The description was Very Good');
when 'C' then dbms_output.put_line('The description was Good');
when 'D' then dbms_output.put_line('The description was Fair');
when 'F' then dbms_output.put_line('The description was Poor');
else dbms_output.put_line('The description was No such Grade');
end case;
end;
/
- - - - - - - - - - - - - - - - Code ends here - - - - - - - - - - - - - - - -
Sample 2:
A simple example demonstrating the proper syntax for a case expression
using a character variable as the selector. See the section entitled
'Restrictions' at the end of this article for details on which PLSQL
datatypes may appear as a selector in a case statement or expression.
- - - - - - - - - - - - - - - - Code begins here - - - - - - - - - - - - - - - -
set serveroutput on
declare
achar char(1) := '&achar';
description varchar2(20);
begin
description := case achar
when 'A' then 'Excellent'
when 'B' then 'Very Good'
when 'C' then 'Good'
when 'D' then 'Fair'
when 'F' then 'Poor'
else 'No such grade'
end;
dbms_output.put_line('The description was ' || description);
end;
/
- - - - - - - - - - - - - - - - Code ends here - - - - - - - - - - - - - - - -
NOTE: The above simple samples demonstrate two subtle differences in the syntax required for case statements and expressions.
1) A case STATEMENT is terminated using the 'end case' keywords; a case EXPRESSION is terminated using only the 'end' keyword.
2) Each item in a case STATEMENT consists of one or more statements, each terminated by a semicolon. Each item in a case expression consists of exactly one expression, not terminated by a semicolon.
Sample 3:
Sample 1 demonstrates a simple case statement in which the selector is
compared for equality with each item in the case statement body. PL/SQL
also provides a 'searched' case statement as an alternative; rather than
providing a selector and a list of values, each item in the body of the
case statement provides its own predicate. This predicate can be any
valid boolean expression, but only one case will be selected.
- - - - - - - - - - - - - - - - Code begins here - - - - - - - - - - - - - - - -
set serveroutput on
declare
achar char(1) := '&achar';
begin
case
when achar = 'A' then dbms_output.put_line('The description was Excellent');
when achar = 'B' then dbms_output.put_line('The description was Very Good');
when achar = 'C' then dbms_output.put_line('The description was Good');
when achar = 'D' then dbms_output.put_line('The description was Fair');
when achar = 'F' then dbms_output.put_line('The description was Poor');
else dbms_output.put_line('The description was No such Grade');
end case;
end;
/
- - - - - - - - - - - - - - - - Code ends here - - - - - - - - - - - - - - - -
Sample 4: This sample demonstrates the proper syntax for a case expression of the type discussed in Sample 3 above.
- - - - - - - - - - - - - - - - Code begins here - - - - - - - - - - - - - - - -
set serveroutput on
declare
achar char(1) := '&achar';
description varchar2(20);
begin
description := case when achar = 'A' then 'Excellent'
when achar = 'B' then 'Very Good'
when achar = 'C' then 'Good'
when achar = 'D' then 'Fair'
when achar = 'F' then 'Poor'
else 'No such grade'
end;
dbms_output.put_line('The description was ' || description);
end;
/
- - - - - - - - - - - - - - - - Code ends here - - - - - - - - - - - - - - - -
Sample 5: This sample demonstrates the use of nested case statements. It is also
permissable to nest case expressions within a case statement (though it
is not demonstrated here), but nesting of case statements within a case
expression is not possible since statements do not return any value.
- - - - - - - - - - - - - - - - Code begins here - - - - - - - - - - - - - - - -
set serveroutput on
declare
anum1 number := &anum1;
anum2 number := &anum2;
answer number;
begin
case anum1
when 1 then case anum2
when 1 then answer := 10;
when 2 then answer := 20;
when 3 then answer := 30;
else answer := 999;
end case;
when 2 then case anum2
when 1 then answer := 15;
when 2 then answer := 25;
when 3 then answer := 35;
else answer := 777;
end case;
else answer := 555;
end case;
dbms_output.put_line('The answer is ' || answer);
end;
/
- - - - - - - - - - - - - - - - Code ends here - - - - - - - - - - - - - - - -
Sample 6: This sample demonstrates nesting of case expressions within another case
expression. Note again the absence of semicolons to terminate both the
nested case expression and the individual cases of those expressions.
- - - - - - - - - - - - - - - - Code begins here - - - - - - - - - - - - - - - -
set serveroutput on
declare
anum1 number := &anum1;
anum2 number := &anum2;
answer number;
begin
answer :=case anum1 when 1 then case anum2
when 1 then 10
when 2 then 20
when 3 then 30
else 999
end
when 2 then case anum2
when 1 then 15
when 2 then 25
when 3 then 35
else 777
end
else 555
end;
dbms_output.put_line('The answer is ' || answer);
end;
/
- - - - - - - - - - - - - - - - Code ends here - - - - - - - - - - - - - - - -
Although PL/SQL anonymous blocks have been used in all of the examples so far,case statements and expressions can also be used in procedures, functions, and packages with no changes to the syntax.
The following samples are included for completeness and demonstrate the use of case statements and/or expressions in each of these scenarios.
Sample 7: This sample demonstrates use of a case statement in a stored procedure.
Note that this sample also demonstrates that it is possible for each of
the items in the case body to consist of more than one statement.
- - - - - - - - - - - - - - - - Code begins here - - - - - - - - - - - - - - - -
set serveroutput on
create or replace procedure testcasestmt ( anum IN number ) is
begin
case
when anum = 1 then dbms_output.put_line('The number was One');
dbms_output.put_line('In case 1');
when anum = 2 then dbms_output.put_line('The number was Two');
dbms_output.put_line('In case 2');
when anum = 3 then dbms_output.put_line('The number was Three');
dbms_output.put_line('In case 3');
when anum = 4 then dbms_output.put_line('The number was Four');
dbms_output.put_line('In case 4');
when anum = 5 then dbms_output.put_line('The number was Five');
dbms_output.put_line('In case 5');
else dbms_output.put_line('The description was Invalid input');
dbms_output.put_line('In the else case');
end case;
end;
/
exec testcasestmt(&anum);
- - - - - - - - - - - - - - - - Code ends here - - - - - - - - - - - - - - - -
Sample 8:
This sample demonstrates the use of a case statement in a stored package.
- - - - - - - - - - - - - - - - Code begins here - - - - - - - - - - - - - - - -
set serveroutput on
create or replace package testpkg2 is
procedure testcasestmt ( anum IN number );
function testcasestmt_f ( anum IN number ) return number;
end testpkg2;
/
create or replace package body testpkg2 is
procedure testcasestmt ( anum IN number ) is
begin
case
when anum = 1 then dbms_output.put_line('The number was One');
dbms_output.put_line('In case 1');
when anum = 2 then dbms_output.put_line('The number was Two');
dbms_output.put_line('In case 2');
when anum = 3 then dbms_output.put_line('The number was Three');
dbms_output.put_line('In case 3');
when anum = 4 then dbms_output.put_line('The number was Four');
dbms_output.put_line('In case 4');
when anum = 5 then dbms_output.put_line('The number was Five');
dbms_output.put_line('In case 5');
else dbms_output.put_line('The description was Invalid input');
dbms_output.put_line('In the else case');
end case;
end;
function testcasestmt_f ( anum IN number ) return number is
begin
case
when anum = 1 then dbms_output.put_line('The number was One');
dbms_output.put_line('In case 1');
when anum = 2 then dbms_output.put_line('The number was Two');
dbms_output.put_line('In case 2');
when anum = 3 then dbms_output.put_line('The number was Three');
dbms_output.put_line('In case 3');
when anum = 4 then dbms_output.put_line('The number was Four');
dbms_output.put_line('In case 4');
when anum = 5 then dbms_output.put_line('The number was Five');
dbms_output.put_line('In case 5');
else dbms_output.put_line('The description was Invalid input');
dbms_output.put_line('In the else case');
end case;
return anum;
end;
end testpkg2;
/
exec testpkg2.testcasestmt(&anum);
variable numout number
exec :numout := testpkg2.testcasestmt_f(&anum);
print numout
- - - - - - - - - - - - - - - - Code ends here - - - - - - - - - - - - - - - -
Sample 9: This sample demonstrates the use of a case expression in a stored package.
- - - - - - - - - - - - - - - - Code begins here - - - - - - - - - - - - - - - -
set serveroutput on
create or replace package testpkg is
procedure testcase ( anum IN number );
function testcase_f ( anum IN number ) return number;
end testpkg;
/
create or replace package body testpkg is
procedure testcase ( anum IN number ) is
anumber number := anum;
anothernum number;
begin
anothernum :=
case when anumber = 1 then anumber + 1
when anumber = 2 then anumber + 2
when anumber = 3 then anumber + 3
when anumber = 4 then anumber + 4
when anumber = 5 then anumber + 5
else 999
end;
dbms_output.put_line('The number was ' || anothernum);
end;
function testcase_f ( anum IN number ) return number is
anumber number := anum;
anothernum number;
begin
anothernum := case when anumber = 1 then anumber + 1
when anumber = 2 then anumber + 2
when anumber = 3 then anumber + 3
when anumber = 4 then anumber + 4
when anumber = 5 then anumber + 5
else 999
end;
dbms_output.put_line('The number was ' || anothernum);
return anothernum;
end;
end testpkg;
/
variable numout number
exec testpkg.testcase(&anum);
exec :numout := testpkg.testcase_f(&anum);
print numout
- - - - - - - - - - - - - - - - Code ends here - - - - - - - - - - - - - - - -
限制声明 The following datatypes ARE NOT supported to appear as the selector expression in a case statement or case expression:
BLOB
BFILE
VARRAY
Nested Table
PL/SQL Record
PL/SQL Version 2 tables (index by tables)
Object type (user-defined type)
All of these types, except for object types, face a similar restriction even for if statements (i.e. they cannot be compared for equality directly), so, this is unlikely to change for these types. Lack of support for object types is simply an implementation restriction which may be relaxed in future releases.